C 11右值引用詳解

2021-09-22 16:38:09 字數 2082 閱讀 1378

< c++11 auto和decltype關鍵字

能出現在賦值號左邊的表示式稱為「左值」,不能出現在賦值號左邊的表示式稱為「右值」。一般來說,左值是可以取位址的,右值則不可以。

非 const 的變數都是左值。函式呼叫的返回值若不是引用,則該函式呼叫就是右值。前面所學的「引用」都是引用變數的,而變數是左值,因此它們都是「左值引用」。

c++11 新增了一種引用,可以引用右值,因而稱為「右值引用」。無名的臨時變數不能出現在賦值號左邊,因而是右值。右值引用就可以引用無名的臨時變數。定義右值引用的格式如下:

型別 && 引用名 = 右值表示式;

例如:

class a{};

a & rl = a(); //錯誤,無名臨時變數 a() 是右值,因此不能初始化左值引用 r1

a && r2 = a(); //正確,因 r2 是右值引用

引入右值引用的主要目的是提高程式執行的效率。有些物件在複製時需要進行深複製,深複製往往非常耗時。合理使用右值引用可以避免沒有必要的深複製操作。例如下面的程式:

#include #include #include using namespace std;

class string

string(const char* s)

string(const string & s)

string & operator = (const string & s)

return *this;

}string(string && s) : str(s.str)

string & operator = (string && s)

return *this;

}~string()

};template void moveswap(t & a, t & b)

int main()

程式的輸出結果如下:

move operator = called

****

this

move constructor called

move operator = called

move operator = called

hello

第 33 行過載了乙個移動賦值號。它和第 19 行的複製賦值號的區別在於,其引數是右值引用。在移動賦值號函式中沒有執行深複製操作,而是直接將物件的 str 指向了引數 s 的成員變數 str 指向的地方,然後修改 s.str 讓它指向別處,以免 s.str 原來指向的空間被釋放兩次。

該移動賦值號函式修改了引數,這會不會帶來麻煩呢?答案是不會。因為移動賦值號函式的形參是乙個右值引用,則呼叫該函式時,實參一定是右值。右值一般是無名臨時變數,而無名臨時變數在使用它的語句結束後就不再有用,因此其值即使被修改也沒有關係。

第 53 行,如果沒有定義移動賦值號,則會導致複製賦值號被呼叫,引發深複製操作。臨時無名變數string("this")是右值,因此在定義了移動賦值號的情況下,會導致移動賦值號被呼叫。移動賦值號使得 s 的內容和 string("this") 一致,然而卻不用執行深複製操作,因而效率比複製賦值號高。

雖然移動賦值號修改了臨時變數 string("this"),但該變數在後面已無用處,因此這樣的修改不會導致錯誤。

第 46 行使用了 c++ 11 中的標準模板 move。move 能接受乙個左值作為引數,返回該左值的右值引用。因此本行會用定義於第 28 行、以右值引用作為引數的移動建構函式來初始化 tmp。該移動建構函式沒有執行深複製,將 tmp 的內容變成和 a 相同,然後修改 a。由於呼叫 moveswap 本來就會修改 a,所以 a 的值在此處被修改不會產生問題。

第 47 行和第 48 行呼叫了移動賦值號,在沒有進行深複製的情況下完成了 a 和 b 內容的互換。對比 swap 函式的以下寫法:

template

void swap(t & a, t & b)

swap 函式執行期間會呼叫一次複製建構函式,兩次複製賦值號,即一共會進行三次深複製操作。而利用右值引用,使用 moveswap,則可以在無須進行深複製的情況下達到相同的目的,從而提高了程式的執行效率。

C 11 左值 右值 右值引用詳解

在c 11中所有的值必屬於左值 右值兩者之一,右值又可以細分為純右值 將亡值。在c 11中可以取位址的 有名字的就是左值,反之,不能取位址的 沒有名字的就是右值 將亡值或純右值 舉個例子,int a b c,a 就是左值,其有變數名為a,通過 a可以獲取該變數的位址 表示式b c 函式int fun...

C 11 左值 右值 右值引用詳解

在c 11中所有的值必屬於左值 右值兩者之一,右值又可以細分為純右值 將亡值。在c 11中可以取位址的 有名字的就是左值,反之,不能取位址的 沒有名字的就是右值 將亡值或純右值 舉個例子,int a b c,a 就是左值,其有變數名為a,通過 a可以獲取該變數的位址 表示式b c 函式int fun...

C 11 左值 右值 右值引用詳解

在c 11中所有的值必屬於左值 右值兩者之一,右值又可以細分為純右值 將亡值。在c 11中可以取位址的 有名字的就是左值,反之,不能取位址的 沒有名字的就是右值 將亡值或純右值 舉個例子,int a b c,a 就是左值,其有變數名為a,通過 a可以獲取該變數的位址 表示式b c 函式int fun...