我學習右值引用和教程告訴我:默認情況下函數返回值常量(右值)?
X foo(); X x; x = foo();
而很明顯,這將是確定,並且更高效,x和之間切換資源指針(句柄) 臨時,然後讓臨時的析構函數破壞x的原始資源。
換句話說,在該 分配的右手邊是一個右值的特殊情況下,我們希望拷貝賦值運算符行動 這樣。
那麼,這是否意味着函數的返回值默認情況下總是恆定的,因此右值呢?如果是的話:他們總是不變的,還是有例外?
我學習右值引用和教程告訴我:默認情況下函數返回值常量(右值)?
X foo(); X x; x = foo();
而很明顯,這將是確定,並且更高效,x和之間切換資源指針(句柄) 臨時,然後讓臨時的析構函數破壞x的原始資源。
換句話說,在該 分配的右手邊是一個右值的特殊情況下,我們希望拷貝賦值運算符行動 這樣。
那麼,這是否意味着函數的返回值默認情況下總是恆定的,因此右值呢?如果是的話:他們總是不變的,還是有例外?
R值和恆定不是同義詞,而是有點正交。以下定義:
struct X {};
const X x;
const X f();
int X();
我們可以歸類如下表達式:
x; // constant lvalue
f(); // constant rvalue
g(); // non-constant rvalue
由於你的特殊的問題:不,不是所有的右值表達式是恆定的。
哇,我總是得知,不管是賦值運算符的左邊,它都是一個右值。這個陳述是正確的嗎?因爲我認爲x不能是賦值op的左邊? – xcrypt
@xcrypt:這對於C++來說是不正確的。左值是你可以接受的地址。而右值是你無法接受的地址。 –
@xcrypt:*可以位於賦值的左側*是對左值/右值意義的簡化。還有其他不同的簡化,我傾向於喜歡對象/值的區別:左值指的是* object *,而右值是* value *。你不能分配給一個*值*,但你也不能分配給一個常量對象。即使在這裏,這也是一個小小的簡化。 –
那麼,這是否意味着函數的返回值默認情況下始終是常量,因此右值呢?如果是的話:他們總是不變的,還是有例外?
號他們是右值當且僅當它們不返回引用類型(cv T&
或cv T&&
)。如果它們的返回類型是const限定的,它們是不變的。
這意味着來自函數X foo()
的返回值是一個右值(如果想要新標準),而不是一個常數。而且,在像x = foo()
這樣的表達式中,我們通常不在乎在賦值期間是否臨時改變,這幾乎是移動語義背後的想法。
你可能會混淆類型,對象和表達。只有表達式具有左值/右值的概念。 表達式foo();
是類型X
的右值。因此,聲明x = foo();
將調用 - 如果可能的話 - x
的成員函數X::operator=(X &&)
。否則,它將綁定到標準X::operator=(X const &)
,因爲rvalues綁定到const引用。
請注意,理論上可能有恆定的rvalues,例如,如果您有一個函數聲明爲X const bar();
。那麼bar()
將不會綁定到X&&
,但僅限於X const &&
(以及X const &
)。儘管如此,這在實踐中沒有用處。
也混淆了_objects_和_expressions_。 –
@ TomalakGeret'kal:好點,補充! –
見this previous question,它告訴我們,無論是右值表達式既不是隱式const
型的,也不是代表由固有不可變的對象。
但是,它是未定義(或禁止—我忘記了)在某些情況下通過右值修改對象。這似乎對通過右值訪問的對象產生了一種條件固有的不變性,並且評估函數調用的結果通常是—,但並非總是如此! —一個右值表達式。
你是否在意解釋你的意思:*它是未定義的許多*情況下通過右值修改一個對象*? –
@DavidRodríguez-dribeas:你是否在意遵循鏈接? (雖然我已將'many'改爲'some') –
術語*未定義*不會出現在任何鏈接的問題中,而我在這裏看不到* undefined *的含義。如果你的意思是*禁止*,那麼你不應該使用* undefined *,因爲它具有不同的含義。 –
§5.2.2/ 10(N3225)規定:
函數調用是一個左值如果結果類型是左值引用類型或一個rvalue參考函數類型,如果結果的x值type是對對象類型的右值引用,否則是一個prvalue。
有趣......但是,函數類型和對象類型之間有什麼區別呢? – xcrypt
rvalue是一個表達式(就像一個函數調用),不像返回值。 – Philipp