左值(lvalue)與右值(rvalue)是 C++ 中極具迷惑性卻又至關重要的概念,尤其在 C++11 引入移動語義後成為核心基石。本文從 C 兼容性出發,層層剖析其本質與陷阱。
a)。3、表達式 a+b)。內置類型右值不可修改、不可加 const/volatile;但自定義類型的右值可調用非 const 成員函數,從而修改自身:
struct S {
int i;
S(int v): i(v) {}
void modify(int v) { i = v; }
};
S getS() { static int c=0; return S(c++); }
int main() {
(getS() = S(2)).modify(323); // 合法!右值調用 operator= 返回左值引用,再調用 modify
getS().modify(32); // 合法!直接在右值上調用非 const 成員函數
}
原因:C++ 允許右值調用成員函數,若該函數非 const 則可修改右值。
const T&,不能綁定到 T&。複製構造/賦值若接受非 const 引用(如 auto_ptr 需修改源對象),則無法接受右值,導致 auto_ptr p(get_ptr()); 編譯失敗。這是 auto_ptr 難用的主因之一。
引入 T&& 專門綁定右值,區分左值引用與右值引用,進而實現 std::move、std::forward、移動構造/賦值,完美解決上述困境。