2011-12-11 123 views
1

我學習右值引用和教程告訴我:默認情況下函數返回值常量(右值)?

X foo(); 
X x; 
x = foo(); 

而很明顯,這將是確定,並且更高效,x和之間切換資源指針(句柄) 臨時,然後讓臨時的析構函數破壞x的原始資源。

換句話說,在該 分配的右手邊是一個右值的特殊情況下,我們希望拷貝賦值運算符行動 這樣。

那麼,這是否意味着函數的返回值默認情況下總是恆定的,因此右值呢?如果是的話:他們總是不變的,還是有例外?

+1

rvalue是一個表達式(就像一個函數調用),不像返回值。 – Philipp

回答

3

R值和恆定不是同義詞,而是有點正交。以下定義:

struct X {}; 
const X x; 
const X f(); 
int X(); 

我們可以歸類如下表達式

x;  // constant lvalue 
f();  // constant rvalue 
g();  // non-constant rvalue 

由於你的特殊的問題:不,不是所有的右值表達式是恆定的。

+0

哇,我總是得知,不管是賦值運算符的左邊,它都是一個右值。這個陳述是正確的嗎?因爲我認爲x不能是賦值op的左邊? – xcrypt

+4

@xcrypt:這對於C++來說是不正確的。左值是你可以接受的地址。而右值是你無法接受的地址。 –

+0

@xcrypt:*可以位於賦值的左側*是對左值/右值意義的簡化。還有其他不同的簡化,我傾向於喜歡對象/值的區別:左值指的是* object *,而右值是* value *。你不能分配給一個*值*,但你也不能分配給一個常量對象。即使在這裏,這也是一個小小的簡化。 –

3

那麼,這是否意味着函數的返回值默認情況下始終是常量,因此右值呢?如果是的話:他們總是不變的,還是有例外?

號他們是右值當且僅當它們不返回引用類型(cv T&cv T&&)。如果它們的返回類型是const限定的,它們是不變的。

這意味着來自函數X foo()的返回值是一個右值(如果想要新標準),而不是一個常數。而且,在像x = foo()這樣的表達式中,我們通常不在乎在賦值期間是否臨時改變,這幾乎是移動語義背後的想法。

1

你可能會混淆類型對象表達。只有表達式具有左值/右值的概念。 表達式foo();是類型X的右值。因此,聲明x = foo();將調用 - 如果可能的話 - x的成員函數X::operator=(X &&)。否則,它將綁定到標準X::operator=(X const &),因爲rvalues綁定到const引用。

請注意,理論上可能有恆定的rvalues,例如,如果您有一個函數聲明爲X const bar();。那麼bar()將不會綁定到X&&,但僅限於X const &&(以及X const &)。儘管如此,這在實踐中沒有用處。

+0

也混淆了_objects_和_expressions_。 –

+0

@ TomalakGeret'kal:好點,補充! –

1

this previous question,它告訴我們,無論是右值表達式既不是隱式const型的,也不是代表由固有不可變的對象。

但是,它未定義(或禁止—我忘記了)在某些情況下通過右值修改對象。這似乎對通過右值訪問的對象產生了一種條件固有的不變性,並且評估函數調用的結果通常是—,但並非總是如此! —一個右值表達式。

+0

你是否在意解釋你的意思:*它是未定義的許多*情況下通過右值修改一個對象*? –

+0

@DavidRodríguez-dribeas:你是否在意遵循鏈接? (雖然我已將'many'改爲'some') –

+0

術語*未定義*不會出現在任何鏈接的問題中,而我在這裏看不到* undefined *的含義。如果你的意思是*禁止*,那麼你不應該使用* undefined *,因爲它具有不同的含義。 –

1

§5.2.2/ 10(N3225)規定:

函數調用是一個左值如果結果類型是左值引用類型或一個rvalue參考函數類型,如果結果的x值type是對對象類型的右值引用,否則是一個prvalue。

+0

有趣......但是,函數類型和對象類型之間有什麼區別呢? – xcrypt