2017-07-26 31 views
1

我對這個問題的廣度遺憾,它只是所有這些細節都緊緊地相互連接..Xvalues VS prvalues:是什麼身份屬性添加

我一直在試圖瞭解具體兩者之間的區別價值類別 - xvalues和prvalues,但我仍然感到困惑。

具有同一性(這使得x值不同從prvalue)在以下問題上SO討論的特性:

Is it correct to say that xvalues have identity and are movable?

首先,接受的答案引用§5/用於定義7的xvalue; cppreference(http://en.cppreference.com/w/cpp/language/value_category)提供了一個更廣泛的xvalue定義 - 即使根據cppreference(以及我也知道的編譯器)我們僅考慮5/7中的2個後面的情況,第一個表達式可以是通用右值,不一定是x值。 那麼哪個來源在這裏更加正確?

無論如何,我試圖爲自己開發的「身份」概念的心智模式是,擁有它的表達式應該保證位於實際程序的數據存儲器中。

正因爲這個原因,字符串文字是左值,它們保證駐留在整個程序運行的內存中,而數字文字是前值,假設存儲在筆直的asm中。

同樣似乎來自prvalue文字,適用於std::move即調用fun(1)時,我們將只能得到在被叫幀參數左值,但調用fun(std::move(1))當x值「那種」 glvalue必須保持在來電者框架。

然而,這個心智模型至少不會與臨時對象一起工作,據我所知,它應該始終在實際的內存中創建(例如,如果一個右值ref-taking func被稱爲fun(MyClass())帶有prvalue參數)。所以我猜這個心智模式是錯誤的。

那麼考慮xvalues的'身份'屬性的正確方法是什麼?我讀過身份證明我可以比較地址,但如果我可以比較地址2 MyClass().member s(xvalue根據cppreference),讓我們說通過將它們通過rvalue參考傳入一些比較函數,然後我不明白爲什麼我不能與2 MyClass() s(prvalue)一樣嗎?這是連接到這個

還有一個來源是這裏的答案: What are move semantics?

注意的是,即使標準::移動(a)是一個右值,對其評價不創建一個臨時對象。這個難題迫使委員會引入第三個價值類別。可以綁定到右值引用的東西,即使它不是傳統意義上的右值,也稱爲xvalue(eXpiring值)。

但是,這似乎與'可以比較地址'和a)我沒有看到這與rvalue的'傳統意義'有什麼不同; b)我不明白爲什麼這樣的理由需要在語言中使用新的值類別(好吧,這允許爲OO意義上的對象提供動態類型,但是x值不僅僅指向對象)。

+2

請注意,新規則(C++ 17)重新定義了prvalues,並引入了一個prvalue-to-xvalue轉換,即「臨時實現」。如果您嘗試將兩個MyClass()prvalues傳遞給比較函數,則它們將作爲參考初始化的一部分進行此轉換。 – Cubbi

+0

@Cubbi hm,你的意思是C++ 17還提供了更多的一致性,這個'保證存儲在內存'的概念,我試圖想出來,或物化的理由純粹保證elision?我明白這個概念遠不是標準的字眼,但從外部的角度來看,它似乎確實符合事物的定義。 – ledonter

+0

似乎更一致,是的。 C++ 14 rvalue ref將「直接」綁定到類prvalue和類xvalue初始值設定項。 ([dcl.init.ref] /5.2)。現在它直接綁定到xvalues,但轉換prvalues並綁定到結果xvalue。 – Cubbi

回答

3

我個人有另一種心理模型,它不直接涉及身份和記憶以及什麼。

prvalue來自「純右值」,而xvalue來自「到期價值」,是這個信息,我在我的心理模型使用:

純右值是指一個對象,它是在「純粹臨時意義「:一種表達方式,編譯器可以絕對肯定地判斷它的評估是一個剛剛創建並且立即過期的臨時對象(除非我們通過引用綁定來延長其生命期)。該對象是在評估表達式時創建的,它將根據「母表達式」的規則而死亡。

相反,一個到期值是計算結果爲基準對一個對象,它是答應即將過期一個表達式。這是它給了你一個承諾,你可以做任何你想要的東西,因爲它將被破壞。但是你不知道這個對象是什麼時候創建的,或者它應該被銷燬的。你只知道你「截獲」了它,因爲它即將死亡。

在實踐中:

struct X; 
auto foo() -> X; 
X x = foo(); 
     ^~~~~ 

在這個例子中評估foo()將導致prvalue。只要看看這個表達式就知道這個對象是作爲foo返回的一部分而創建的,並且在這個完整表達式的末尾將會被銷燬。因爲你知道所有這些事情,你可以序幕它的生命週期:

const X& rx = foo(); 

現在富返回的對象都有它的生命週期prolongued到rx

auto bar() -> X&& 
X x = bar(); 
     ^~~~ 

壽命在這個例子中評估bar()將導致xvaluebar承諾您即將給您一個即將到期的對象,但您不知道何時創建此對象。可以在致電bar(作爲臨時或不臨時)之前創建,然後bar爲您提供rvalue reference。好處是你知道你可以隨心所欲地做任何事情,因爲它不會被用作後綴(例如,你可以從中移動)。但是你不知道這個物體何時應該被銷燬。因此你不能延長它的生命週期 - 因爲你不知道它的原始壽命是擺在首位的內容:

const X& rx = bar(); 

這不會延長壽命。

0

當調用func(T&& t)時,調用者說「這裏有一個」,還有「我不在乎你對它做了什麼」。C++沒有指定「here」的性質。

在引用參數作爲地址實現的平臺上,這意味着必須存在某個對象。在該平臺身份==地址。然而,這不是語言的要求,而是平臺調用約定。

一個平臺可以簡單地通過安排在調用者和被調用者中以特定方式註冊對象來實現引用。這裏的身份可以是「註冊edi」。

相關問題