C++11 學習筆記-05.rvalue references

引用聲明

聲明具名變量爲引用,即既存對象或函數的別名。

左值和右值的概念

左值是可以放在賦值號左邊可以被賦值的值;左值必須要在內存中有實體;
右值當在賦值號右邊取出值賦給其他變量的值;右值可以在內存也可以在CPU寄存器。
一個對象被用作右值時,使用的是它的內容(值),被當作左值時,使用的是它的地址。

語法

聲明具名變量爲引用,即既存對象或函數的別名。


& attr(可選) 聲明符 (1)
&& attr(可選) 聲明符 (2) (C++11 起)

  • 左值引用聲明符:聲明 S& D; 將 D 聲明爲到 聲明說明符序列 所確定的類型 S 的左值引用。
  • 右值引用聲明符:聲明
    S&& D; 將 D 聲明爲到 聲明說明符序列 所確定的類型 S 的右值引用。

右值引用

值引用可用於爲臨時對象延長生存期(注意,左值引用亦能延長臨時對象生存期,但不能通過左值引用修改它們):

#include <iostream>
#include <string>
 
int main()
{
    std::string s1 = "Test";
//  std::string&& r1 = s1;           // 錯誤:不能綁定到左值
 
    const std::string& r2 = s1 + s1; // okay:到 const 的左值引用延長生存期
//  r2 += "Test";                    // 錯誤:不能通過到 const 的引用修改
 
    std::string&& r3 = s1 + s1;      // okay:右值引用延長生存期
    r3 += "Test";                    // okay:能通過到非 const 的引用修改
    std::cout << r3 << '\n';
}

懸垂引用

儘管引用一旦初始化,就始終指代一個有效的對象或函數,但有可能創建一個程序,被指代對象的生存期結束,但引用仍保持可訪問(懸垂(dangling))。訪問這種引用是未定義行爲。 一個常見例子是返回自動變量的引用的函數:

std::string& f()
{
    std::string s = "Example";
    return s; // 退出 s 的作用域:
              // 調用其析構函數並解分配其存儲
}
 
std::string& r = f(); // 懸垂引用
std::cout << r;       // 未定義行爲:從懸垂引用讀取
std::string s = f();  // 未定義行爲:從懸垂引用複製初始化

注意,右值引用和到 const 的左值引用能延長臨時對象的生存期.這是一種危險的做法。

若被指代對象被銷燬(例如通過顯式的析構函數調用),但存儲尚未被解分配,則到生存期外的對象的引用仍能以有限的方式使用,且當在同一存儲中重新創建對象時也可以變爲有效(細節見在生存期之外進行訪問)。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章