2010-07-09 33 views
1

有人推測「Temporaries are rvalues」。我說「不」,並給了他下面的例子Rvalues vs temporaries

double k=3; 

double& foo() 
{ 
    return k; 
} 

int main() 
{ 

    foo()=3; //foo() creates a temporary which is an lvalue 
} 

我的解釋是否正確?

+1

您的意思是*左值*,因爲您在表達式的左邊看到它*這是一箇舊式的定義,不再適用於C++。 – fredoverflow 2010-07-09 14:38:12

+1

@FredOverflow:'你的意思是左值,因爲你在表達式的左邊看到它嗎?'不,因爲我知道'參考是_lvalues_' – 2010-07-09 14:43:49

+1

@FredOverflow - 他的例子顯示了左邊的返回值,朋友聲明暗示臨時工只能在右側。 – sje397 2010-07-09 14:44:33

回答

9

臨時和右值是不同的(但相關的)概念。暫時是對象的財產。非臨時性對象的示例是局部對象,全局對象和動態創建的對象。

作爲一個右值是表達式的性質。 rvalues的反義詞是左值,如名稱或取消引用的指針。陳述「臨時是rvalues」是沒有意義的。這裏是右值和臨時對象之間的relationsip:

右邊的值可以是對評估創建其在該詞法包含右值全表達的端部被破壞的暫時對象的表達式。

請注意,左值也可以表示臨時對象!

在函數內嗒嗒,左值s表示由計算表達式std::string("test")創建的臨時對象。

你的評論「引用是左值」也是沒有意義的。引用不是表達式,因此不能是左值。你真正的意思是:

表達function()是一個左值如果函數返回一個參考。

+0

在我看來,你需要在'void blah(const std :: string&s)'中使用const來防止可能是暫時的s變爲左值。這個右值的定義也很笨拙。你會如何定義左值?在我看來,右值/左值表示任務的方向。 rvalue是賦值,lvalue是賦值給rvalue的對象。 – doc 2010-07-09 16:04:24

+0

臨時值是右值,綁定到臨時值的常量值是左值。 §3.10/ 6和§5.2.3/ 1都聲明'std :: string(「test」)是一個右值。有一個非常精細的線... – 2010-07-09 16:44:47

+1

@大衛羅德里格斯 - dribeas:這是我卑微的意見。術語rvalue和左值從C(或者甚至Fortran?)開發,很久以前。它們在分配操作過程中被使用,並且我認爲從其主要定義和使用案例中得出的結論重新定義它們是錯誤的。 – doc 2010-07-09 16:56:14

7

不可以。您正在返回對全局雙引號的引用,而不是臨時引用。

同樣的測試與真正的臨時會:

double foo() { return 3.0; } 
int main() { 
    foo() = 2.0; // error: lvalue required as left operand of assignment 
} 

編輯: 答案本來是剛剛確定的例子是錯誤的,我並沒有真正想進入的更深層次的討論不管臨時是否是右值......正如其他人所說的那樣,左值或右值是表達式的屬性,而不是對象的屬性(在最一般的意義上,不僅是類實例)。然後再次,標準說:

§3.10/ 5調用不返回引用的函數的結果是一個右值。用戶定義的運算符是函數,這些運算符是否期望或產生左值取決於它們的參數和返回類型。

§3.10/ 6一個表達式將轉換後的臨時對象保存爲非引用類型是一個右值(這包括使用函數表示法(5.2.3)顯式創建一個對象)。

哪個AFAIK是創建臨時對象的情況。現在,你也可以將一個常量引用綁定到一個臨時對象,在這種情況下,你將得到一個新的變量(引用),它可以被用作一個有效地引用臨時對象的左值。

細線是創建臨時表達式是右值表達式。您可以將一個常量引用綁定到該表達式的結果,以獲取可用作常量限定左值表達式的變量。

+0

@David:據我所知,無名_objects_是臨時的。在這種情況下,當調用'foo()'時會創建一個無名對象,那麼您怎麼能說它不是臨時的呢? – 2010-07-09 14:35:10

+0

@user標量rvalues表示值,而不是對象。沒有這樣的東西作爲一個臨時的雙重對象。 – fredoverflow 2010-07-09 14:39:20

+0

@ user242265:在您的示例中,沒有無名稱的對象; 'foo()'返回一個對'k'的引用,這是一個左值。在David的例子中,'foo()'的結果是一個右值,所以你不能指定它。 – 2010-07-09 14:43:12

0

臨時保護不會變成左值,現在稱爲右值。但是,由於移動語義,C++ 0x將允許臨時變成左值。像在這個愚蠢的片段

void blah(ICanBeTemporary && temp) 
{ 
    temp.data = 2; //here temporary becomes lvalue 
} 


//somewhere 
blah(ICanBeTemporary("yes I can")); 

現在我們有術語混亂。人們過去稱爲臨時rvalues,這被稱爲右值參考。現在被命名的對象被認爲是非右值引用的。

+0

在任何情況下,對象都不會變成左值或右值。只是多個表達式可以表示同一個(臨時)對象,並且每個表達式都可以是左值或右值。 – fredoverflow 2010-07-09 23:16:00

+0

@FredOverflow:但臨時名稱被稱爲rvalues - 上面稱爲* rvalue引用* - 引用什麼?表達!?或者說是一個對象?那麼* rvalue *真正表示什麼? – doc 2010-07-10 21:22:15

+0

引用始終引用對象。只是某些類型的引用只能由*某些表達式在語法上初始化。這並不意味着引用*表示*表達式。在運行時,不存在左值或右值。 – fredoverflow 2010-07-11 11:24:53

相關問題