C++11的左值引用與右值引用總結


概念

在C++11中,區別表達式是左值或右值可以做這樣的總結:當一個對象被用作右值的時候,用的是對象的值(內容);當對象被用作左值的時候,用的是對象的身份(在內存中的位置)。左值有持久的狀態,而右值要么是字面常量,要么是在表達式求值過程中創建的對象,即左值持久,右值短暫

以上的定義來自於C++Primer(5th)第121頁和第471頁。可能令人困惑,看了接下來的例子就明白了

[cpp]  view plain  copy
  1. int &&rr1 = 42;//正確,字面常量是右值  
  2. int &&rr2 = rr1;//錯誤,表達式rr1是左值  

特性中的應用

    decltype關鍵字

        使用關鍵字decltype的時候,左值和右值有所不同。如果表達式的求值結果是左值,decltype作用於該表達式(不是變量)得到一個引用類型,例如,假定p的類型是int*,因為解引用運算符生成左值,所以decltype(*p)的結果是int&。另一方面,因為取地址運算符生成右值,所以decltype(&p)的結果是int**,也就是說,結果是一個指向整型指針的指針。

    lambda表達式

        lambda表達式是形如auto f = [ ]{ }的函數。

        lambda可指定其捕獲列表的類型,[&]表示捕獲列表采用隱式引用捕獲方式lambda函數體中所使用的來自所在函數的實體都采用引用方式使用,[=]表示采用值捕獲方式。

[cpp]  view plain  copy
  1. /*f1的sz是隱式值捕獲,f2的sz是隱式引用捕獲  
  2. auto f1 = [=](const string &s)  
  3.       { return s.size() >=sz; }  
  4. auto f2 = [&](const string &s)  
  5.       { return s.size() >=sz; }  

    拷貝控制

    移動構造函數使用右值引用的形參

[cpp]  view plain  copy
  1. class Foo  
  2. {  
  3.    //移動構造函數  
  4.    Foo(Foo&&);  
  5. };  

    引用折疊和實參推斷

    實參推斷,按照實參和形參匹配的規則。
    引用折疊:
           通常情況下,我們不能將一個右值引用綁定到一個左值上,但是C++語言在正常綁定規則外定義了兩個例外規則,允許這種綁定。
    第一個例外規則影響右值引用的參數推斷如何進行: 當我們將一個左值傳遞給函數的右值引用參數,且此右值引用指向模板類型參數(如T&&),編譯器推斷模板類型參數為實參的左值引用類型。
[cpp]  view plain  copy
  1. //編譯器推斷T類型是int&(左值引用),而非int  
  2. template <typename T> void f(T&&);  
  3. int i = 0;  
  4. f(i);  

    引用折疊:在所有情況下(除了一個例外),引用會折疊成一個普通的左值引用類型。

    

[html]  view plain  copy
  1. 即:對於一個給定類型X  
  2. <ol>  
  3. <li>X& & ,X& && ,X&& &都折疊成類型X&<li>  
  4. <li>類型X&& &&折疊成X&&<li>  
  5. </ol>  
    注:引用折疊只能應用於間接創建的引用的引用,如類型別名或模板參數。


這兩個規則導致了兩個重要結果:

    如果一個函數參數是一個指向模板類型參數的右值引用(如T&&),則他可以被綁定到一個左值。且

    如果實參是一個左值,則推斷出的模板實參類型將是一個左值引用,且函數參數將被實例化為一個普通的左值引用參數(T&)

也暗示了:我們可以將任意類型的實參傳遞給T&&類型的函數參數。

    函數重載

    重載函數定義兩個版本,一個版本接受一個指向const的左值引用,第二個版本接受一個指定非const的右值引用。即可接受所有可轉換成當前類型的對象
    
[cpp]  view plain  copy
  1. void Foo(const X&);  
  2. void Foo(X&&);  

   我們知道,非常量可以初始化一個底層const,反過來卻不行,所以第一種版本可以接收任何能轉換成類型X的任何對象。第二種版本只可以傳遞非const右值,由於精確匹配規則,傳遞非const右值時,會調用第二種版本,盡管第一種版本也可以接受。

   一般來說,我們不需要為函數操作定義接受一個const X&&或是一個普通的X&參數的版本。當我們希望從實參“竊取‘數據時,通常傳遞一個右值引用。為了達到這一目的,實參不能使const的。類似的,從一個對象進行拷貝的操作,不應該改變該對象,因此,通常不需要定義一個接受一個普通的X&參數的版本。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM