![](/img/trans.png)
[英]Dispatching r-values and l-values differently and using sfinae to disable one option
[英]Confused with r-values and l-values
我最近在C ++ 11的白皮書上讀過,如果我寫的話,
void foo(X&)
這將被稱為l值而不是r值
如果我寫,
void foo(const X&)
這將被調用r值和l值。
有人能給我一個例子,這意味着什么?
此函數接受左值引用
void foo(X&)
並試圖用右值調用它會產生錯誤。
此函數需要一個const
左值引用
void foo(const X&)
但有一個問題:
可以使用右值來初始化const左值引用,在這種情況下,由rvalue標識的對象的生命周期被延長,直到引用的范圍結束。
因此,最后一個函數接受左值和右值參數
struct X {};
void foo(X&) {
}
void fooC(const X&) {
}
int main() {
X obj;
// foo(std::move(obj)); // Error - non-const
foo(obj); // Valid
fooC(obj); // Valid
fooC(std::move(obj)); // Valid
}
有關更多信息,請查看此處: 參考初始化或檢查[dcl.init.ref] / p5
考慮以下代碼:
int i = 58;
什么是58
? 這是一個字面常量 。
因此: foo (const int&)
58
是一個r值(在這種情況下也是一個文字常量),因為你不能直接引用它,並且,比方說,修改它,因為沒有辦法做到這一點。 您可以引用i
因為它有一個名稱,一個標識符,但58
本身沒有標識符。
通俗地說,如果某些東西存在但它沒有聲明的名稱你可以訪問它然后它是一個常量和一個r值,除非你用r-val引用int &&引用它,那么你可以改變它。
int f();
...
int x = f(); //the returned int is an r-value, but x is an l-value
當你聲明foo函數時
void foo(X&)
然后這樣的代碼將無法編譯:
foo(5);
但如果你聲明它:
void foo(const X&)
然后你可以這樣稱呼它:
foo(5);
const literal 5是一個r值,因為它沒有名字。
粗略地說,rvalues是臨時對象(從函數返回),而lvalues也是你可以引用的對象。
例如:
X bar();
X x = bar();
在該代碼中(忽略可能的編譯器優化),創建一個臨時X對象來保存返回的foo值並傳遞給x
的copy-constructor,這個臨時對象是一個rvalue,只存在於這個語句中,不能被引用代碼的其他部分。 x
然后是左值,您可以檢索其地址並在以后引用它。
這兩個功能
void foo(X &);
void foo(const X &);
分別期待左值,非常量和常量。 后者接受rvalues的原因是因為rvalues可以轉換為對lvalues的const引用。 也就是說,你可以這樣做:
const X &ref = bar();
這里由bar()返回的臨時值在ref
超出范圍之前不會被銷毀,因此它的生命周期已延伸到語句之外。 但是你不能對非const引用做同樣的事情,
X &ref = bar(); // Error!
這是不允許的,因為bar的返回值是臨時值(rvalue)並且無法修改。
但請注意,這不是C ++ 11的功能,這已經存在。 新功能是指定右值引用的功能
void foo(X &&);
void foo(const X &&);
這引入了更加微妙的情況,例如參見C ++ 11中的Universal References - Scott Meyers 。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.