C++中的右值引用


C++中的右值引用

摘要

本文介紹C++中右值引用的含義、以及注意事項。

右值引用的含義

《C++ primer》第5版中說明了右值引用的含義:

所謂右值引用就是必須綁定到右值的引用

舉例來說:

int i = 42;
int &r = i; // 左值引用綁定到左值上
int &&rr = i; // 錯誤,右值引用不能綁定到左值上
int &&rri = i * 42; //正確,i*42是右值

此外,《C++ primer》中還說明了右值引用的重要性質:

只能綁定到一個將要銷毀的對象

需要注意的是,右值引用變量本身是左值,所以不能用一個右值引用變量初始化一個右值引用。

int &&rx = rri; //錯誤,rri是一個右值引用變量,是左值

那么,到底為什么說一個右值引用變量是一個左值呢?左右值的理解就是,

  • 程序員可以取地址的是左值。
  • 程序員不能取地址的是右值。
    這里,rri是一個變量,具有名字,可以取地址,所以說是左值。

左值引用和右值引用的區別

學了左值引用和右值引用,自然要問這兩個的區別是什么?左值引用和右值引用的區別就是初始化使用的規則不一樣,其余都一樣。

左值引用:只能使用左值進行初始化(除了,常量左值引用可以使用字面量初始化)
右值引用:只能使用右值初始化

在使用的時候,左值引用和右值引用無任何區別。

編譯器如何對待右值引用?

既然右值引用只能綁定到右值上,並且右值引用變量本身是左值,自然就有以下疑問:
問題1:右值引用綁定的是右值,而右值是將要消亡的,但是右值引用變量本身又是左值,左值就代表着是持久的。那么把編譯器是如何實現的?
問題2:按照我的這篇隨筆中的理解,我把右值理解成水,把引用理解成標簽,那么把一個右值引用(標簽)綁定到了右值(水)上,就說不通了,怎么解釋?

來看一下匯編代碼:


右值引用的反匯編例子
可以看出,當一個右值引用變量綁定到右值的時候,編譯器會將右值存儲到棧內存中,並且將該地址賦值給右值引用。

也就是說,當一個即將消亡的值被一個右值引用變量綁定時,編譯器會先把該值保存到棧上,然后把保存位置的內存地址賦值給右值引用。 從水桶和水的關系解釋,編譯器先創建了一個水桶,把水倒進水桶,並把標簽貼到該水桶上。這就是當一個右值引用綁定到右值時,編譯器的做法。

用法

當然,平時使用的話還是無需關心編譯器怎么處理的細節,只需要關心什么時候能用,什么時候不能用就行了。
什么時候不能用:

  • 函數返回內部變量的右值引用:
    比如:
int && test() {
    int x = 1;
    return x + 1; // 未定義行為,最好別用
}

什么時候能用:
右值引用主要的用途:

  • 實現移動語義。
  • 實現完美轉發。

總結

本文關鍵點:

  • 右值引用只能綁定到右值上。
  • 右值引用變量是左值。
  • 右值引用變量指向的是一片內存,這片內存中存了值。所以,一個函數不能返回內部值的右值引用。
  • 使用右值引用實現移動語義和完美轉發。

參考


免責聲明!

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



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