首先,程式中有左值和右值的概念:
右值:read value 可讀的值,通常指代賦值運算=右側的常量值,字面值,或者函式的返回值,它們沒有具體的指代名,即無法通過位址訪問,通常在賦值表示式結束後變銷毀。
int value=fun();
對於該賦值表示式,表示式左邊的value為左值,可以被賦值,而fun()的返回值是臨時存放的右值,語句結束後便銷毀。
左值引用:也就是通常所述的引用,引用是原先左值的別名,在定義時完成初始化,並且不可以作變更。
int & value=i;
其本質是左值引用與被引用的左值共同代表同一位址上的內容,即訪問的是同乙份資料。
左值引用和左值共同使用記憶體中同乙份內容資料。
左值引用的作用:
函式在傳值方式傳遞引數,以及返回函式值(例如返回型別為類型別),都會執行拷貝構造。
即: 實參=》形參: 執行一次拷貝 函式返回: 執行一次拷貝
若引數或返回值是複雜的類型別,將帶來大量無畏的拷貝構造開銷。
檢視以下**:
#include using namespace std;
class copyable
copyable(const copyable &o)
};copyable returnrvalue()
void pass_val(copyable a)
void pass_ref(const copyable& a)
int main()
上述**中:
returnrvalue() 在函式內部構造乙個物件,然後返回:將呼叫一次拷貝建構函式
pass_val() 為傳值傳參:將呼叫一次拷貝建構函式
pass_ref() 採取傳引用方式,由於指向的是同乙份內容,將不會進行拷貝構造。
returnvalue()的返回值是乙個右值(匿名) 它立即被作為引數傳入 pass_val 期間進行了2次無意義的拷貝構造。
因此,編譯器通常會對返回值進行優化:g++ 編譯執行後結果如下:
然而在c++ standard中並未要求編譯器,即在語言層面仍然存在一些可優化的部分。
通過 -fno-elide-constructors 關閉返回值優化,輸出結果如下:
因此,針對此類問題,需要移動技術,避免無意義的拷貝賦值操作,c++11提出右值引用的概念,其本質是接替右值的所有權。
int &&value=11;//右值引用乙個常量值
int &&value=fun();//右值引用乙個臨時的函式返回值
移動技術:不銷毀原先的記憶體內容,而是將所有權移交給被交付的物件。
而一般的右值(生命期很短,通常一行表示式後即結束),將其所有權交出是安全的。
因此,右值引用的方式是:在右值被銷毀之前,利用其已存在的資源,交由給其它部分引用使用。
c++11引入的右值引用帶來了深刻的效能提公升,改變了以往複製,拷貝的繁瑣操作,轉而採取更為智慧型的移動技術,其本質通過移交所有權,在不改變記憶體內容情況下,完成資源的轉移。
主要應用在stl的,例如vector的擴容:
當vector的size增大到capacity的一定比例後,需要申請一片更大的記憶體空間,同時將原先的資料轉移到新空間。在移動技術之前,這意味著大量元素的深拷貝,而採取移動技術,無需釋放原先空間,而只需要將原先空間所有權交由給新空間建立者即可。
c 11 右值引用
右值引用 是一種復合型別,跟c 的傳統引用很類似。為更準確地區分兩種型別,我們把傳統的c 引用稱為 左值引用 而使用 引用 這一術語時,我們的意思同時包含兩種引用 左值引用和右值引用。右值引用的行為跟左值引用類似,不同之處在於 右值引用可以繫結到臨時量 右值 而 非const的 左值引用卻不能繫結到...
C 11 右值引用
消除兩個物件互動時不必要的物件拷貝,節省運算儲存資源,提高效率。能夠更簡潔明確地定義泛型函式。1.右值引用 int a a 1 here,a is an lvalue 上述的a就是乙個左值。c 11中左值的宣告符號為 為了和左值區分,右值的宣告符號為 printreference const str...
C 11右值引用
c 11中引入的乙個非常重要的概念就是右值引用。理解右值引用是學習 移動語義 move semantics 的基礎。而要理解右值引用,就必須先區分左值與右值。對左值和右值的乙個最常見的誤解是 等號左邊的就是左值,等號右邊的就是右值。左值和右值都是針對表示式而言的,左值是指表示式結束後依然存在的持久物...