C 11 右值引用

2021-10-25 02:08:03 字數 2667 閱讀 6518

右值引用的目的主要是為了是減少記憶體拷貝,優化效能。

左值右值

賦值操作符「=」的左側,通常是乙個變數

賦值操作符「=」的右側,通常是乙個常數、表示式、函式呼叫

表示式結束後依然存在的持久化物件

表示式結束時就不再存在的臨時物件

左值可以運用&操作符取得位址

右值(臨時物件)無法取得位址

左值一般有名字

右值一般沒有名字

c++11以前,就有左值引用,簡稱引用,左值引用就像是給變數起了別名,操作這個別名就跟操作原變數名一樣。

int x =20;

int& rx = x;

// 定義左值引用時必須初始化

c++11以前,右值被認為是無用的資源,而c++11引入右值引用,就是為了重用右值。定義右值引用需要使用&&:

int

&& rrx =

200;

//rrx本身是乙個左值,但是裡面存放的是200這個右值的位址,只要rrx仍存在,200這個右值就不會被銷毀。

int& lx = rrx;

//lx等於10,對lx的改變同樣會作用到rrx

右值引用只可以引用右值:

x a;

x f();

x& r1 = a;

// 將r1繫結到a(乙個左值)

x& r2 =f(

);// 錯誤:f()的返回值是右值,無法繫結

x&& rr1 =f(

);// ok:將rr1繫結到臨時變數

x&& rr2 = a;

// 錯誤:不能將右值引用rr2繫結到左值a

移動語義

c++11引入右值引用的意義就是為了實現移動語義。比如,類的右值是乙個臨時物件,如果沒有被繫結到右值引用上,這個臨時物件在表示式結束時就會被廢棄。所以我們可以在右值被廢棄之前,移走它的資源進行廢物利用,從而避免無意義的複製。其中以同型別的右值構造物件時,需要以右值引用形式傳入引數,然後移走這個臨時物件的資源(以前是複製臨時物件的資源)。

比如用c++實現乙個字串類mystringmystring內部開闢和管理乙個c語言的char *陣列,這個時候一般都需要自己實現拷貝建構函式和拷貝賦值函式(因為c++預設的拷貝是淺拷貝,只會直接複製指標,但指標這種資源不能共享,不然乙個析構了,另乙個也就完蛋了)

int

main()

cout << mystring::cctor << endl;

}

push_back函式會對傳遞進來的引數進行一次拷貝(呼叫拷貝建構函式),並將其新增到vector中。因此上述**會執行1000次拷貝建構函式。在每次迭代中執行的操作如下:

呼叫mystring("hello")構造出臨時物件,這個臨時物件是乙個右值。

把臨時物件複製乙個(呼叫mystring的拷貝建構函式),放到vecstr中。

mystring("hello")只是臨時物件,拷貝完就沒用了,進行析構釋放。

下一輪又重新構造臨時物件以及拷貝。

最理想的情況下,臨時物件構造出來後,應該直接交給vecstr,而不是把內容複製一遍後析構掉,造成沒有意義的資源申請和釋放操作。而c++11新增加的移動語義就能夠做到這一點。

要實現移動語義就必須增加兩個函式:移動建構函式和移動賦值建構函式。以移動建構函式為例,對比普通的拷貝建構函式和移動建構函式:

// 普通的拷貝建構函式

mystring

(const mystring& str)

// 移動建構函式

mystring

(mystring&& str)

noexcept

:m_data

(str.m_data)

mystring("hello")是個臨時物件,是個右值,優先進入移動建構函式而不是拷貝建構函式(移動構造函式引數使用右值引用),它並不是重新分配一塊新的空間、將要拷貝的物件複製過來,而是"偷"了過來,即複製臨時物件的指標,使得自己的指標指向臨時物件的資源,然後將臨時物件的指標修改為nullptr,這樣臨時析構的時候就無法釋放其資源(否則它把資源釋放了,那偷來的資源就沒有了)。

複製與移動的區別如下,可以看到move構造是直接搶了臨時物件的資源:

對於乙個左值,肯定是呼叫拷貝建構函式了,但是有些左值是區域性變數,生命週期也很短,能不能也移動而不是拷貝呢?c++11為了解決這個問題,提供了std::move()方法來將左值轉換為右值,從而方便應用移動語義。我覺得它其實就是告訴編譯器,雖然我是乙個左值,但是不要對我用拷貝建構函式,而是用移動建構函式吧。

更具體的講解和例子看[c++11]我理解的右值引用、移動語義和完美**,這部落格講的很好。

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 的基礎。而要理解右值引用,就必須先區分左值與右值。對左值和右值的乙個最常見的誤解是 等號左邊的就是左值,等號右邊的就是右值。左值和右值都是針對表示式而言的,左值是指表示式結束後依然存在的持久物...