以前以為自己把左值和右值已經弄清楚了,果然發現自己還是太年輕了,下面的這些東西是自己通過在網上拾人牙慧,加上自己的理解寫的。
1.
2. 怎么區分左值和右值:知乎大神@顧露的回答。
3. 我們不能直接定義一個引用的引用。但是,通過類型別名或通過模板類型參數間接定義是可以的。
引用折疊只能應用於間接創建引用的引用,如類型別名或模板參數。(C++ Primer 第609頁)。
聯想:可以定義指針的指針,也可以定義指針的引用。
4. move 永遠把東西變成右值,而我們可以使用forward傳遞那些定義為模板類型參數的右值引用的函數參數,通過其返回類型上的引用折疊,
forward可以保持給定實參的左值/右值屬性。
右值引用和返回值優化經常被很多人混在一起,而且最要命的是如果開了優化的話,其實多半輸出的代碼是一樣的。(via 知乎@vczh)
5. 具名的右值引用是左值,不具名的右值引用是右值。(將亡值的來源)
返回不具名的右值引用主要有兩種情況:
1 static_cast<T&&> (t); 2 T&& fun 3 { 4 return t; 5 }
正是因為返回了將亡值(不具名的右值引用),所以才可以把它們的返回值綁定到一個右值引用上。
參考:話說C++的左值、右值、將亡值。
6. T&& t (T為模板參數) 在發生自動類型推斷的時候,它是未定的引用類型(universal references),如果被一個左值初始化,它就是一個左值;
如果它被一個右值初始化,它就是一個右值,它是左值還是右值取決於它的初始化。(聯想到為模板元編程發明的引用折疊規則)。
需要注意的是,僅僅是當發生自動類型推導(如函數模板的類型自動推導,或auto關鍵字)的時候,T&&才是universal references。
沒有自動類型推導的過程中,類型是確定的,是右值引用類型,只能綁定到一個右值上。
一篇我認為寫的非常好的文章:從4行代碼看右值引用。
7. 另外,網上介紹的一個VS的 bug 是允許函數返回局部對象的左值引用,這是不符合C++標准的。
但是可以返回右值引用和const左值引用。
8. 字面值常量中僅有字符串字面值是左值,可以用&取地址,其他的都是右值。
1 "abc" //左值,可以取地址 2 char* ptr = "abc"; //正確的寫法 3 const char* ptr = "abc"; //正確的寫法 4 char a[] = "abc"; char* ptr = a; //正確的寫法 5 const char* ptr = & "abc" //錯誤的寫法
"abc"可以直接初始化指針const char*,指針的值為字符串"abc"的首字符a的地址,但不能直接初始化char* 指針。(更正,是可以初始化char*指針的)
而&("abc")被編譯器編譯為const的指向數組的指針const char (*) [4](之所以是4,是因為 編譯器會在"abc"后自動加上一個'\0'),它不能初始化char *類型,即使是 const char *也不行。