­

C++ 右值引用與 const 關鍵字

C++11 新增了另一種引用:右值引用(rvalue reference),這種引用可指向右值,是使用 && 聲明的。使用右值引用可以減少複製操作,延長臨時對象生命周期,提升程序性能。它一般被用來實現移動語義完美轉發,將 const 關鍵字用於右值引用的場景不多,這裡來總結一下 const 右值引用的特性,對其是否具有實際應用價值不做討論。右值引用必須在創建的同時進行初始化,且只能使用右值進行初始化,可將 const 關鍵字用於右值引用,如下所示:

//聲明並初始化常規右值引用變量
int && rrx = 55;

//將const關鍵字用於右值引用變量,以下幾種為等效表示
const int && crrx = 55;
int const && crrx = 55;

Microsoft Visual Studio 中連續多個 const 會被編譯器解釋成一個,即 const const const const int &&const int && 等效,除此之外,const int const &&Microsoft Visual Studio 中也與 const int && 等效,而 int && constQT minGW 中將會報錯,在 Microsoft Visual Studio 中與 int && 等效。

常規右值引用與 const 右值引用的特性如下:

  • 類型為 int && 的引用只能用來引用右值,不能用來引用左值,後面可修改其值。可將類型為 int 的非左值(比如字面常量 100、多項表達式 1+50*2、函數的 int 返回值)、類型不是 int 但可轉換為 int 的非左值(比如多項表達式 1.0+50.0*2.0、字面常量 100.0、函數的 double 返回值)在初始化時賦給 rrx。變量初始化完成後,其地址就固定不變,其表現與 int 類型變量一致,右值引用變量自身屬於左值。
  • 類型為 const int && 的引用也只能用來引用右值,不能用來引用左值,但後面不可修改其值。可將類型為 int 的非左值(比如字面常量 100、多項表達式 1+50*2、函數的 int 返回值)、類型不是 int 但可轉換為 int 的非左值(比如多項表達式 1.0+50.0*2.0、字面常量 100.0、函數的 double 返回值)在初始化時賦給 crrx。變量初始化完成後,其地址就固定不變,其表現與 const int 類型變量一致,自身也屬於左值。

常規右值引用變量的初始化用法如下:

//初始化方式一:字面常量
int && rrx = 100;
int && rrx = 100.0;

//初始化方式二:多項表達式
int && rrx = 1+50*2;
int && rrx = 1.0+50.0*2.0;

//初始化方式二:函數返回值
int && rrx = abs(10);
int && rrx = sqrt(10.0);

右值引用在部分情況下會生成臨時變量(一個典型例子是使用字面常量右值如 100 來初始化右值引用變量),然後將右值引用變量作為該臨時變量的別名,這與 const 左值引用十分相似,但與之不同的是:const 左值引用變量初始化完成後其值就無法被修改(權限為只讀),右值引用變量初始化完成後其值仍可修改(權限為可讀可寫)。在另一些情況下,右值引用可以延長已有臨時變量的生命周期,減少複製操作的次數(一個典型例子是使用函數返回的類對象來初始化右值引用變量,在關閉編譯器優化的情況下可以將本需 2 次的複製操作減少為 1 次)。

const 關鍵字修飾的右值引用變量初始化用法如下,與常規右值引用變量的區別僅在於它們的可修改屬性不同

//初始化方式一:字面常量
const int && crrx = 100;
const int && crrx = 100.0;

//初始化方式二:多項表達式
const int && crrx = 1+50*2;
const int && crrx = 1.0+50.0*2.0;

//初始化方式二:函數返回值
const int && crrx = abs(10);
const int && crrx = sqrt(10.0);

將初始化時 int &&const int && 可接受的形式列個表,如下,需要注意的是:可以將右值引用變量用於初始化左值引用變量,但不可將左值引用變量用於初始化右值引用變量,因為右值引用變量自身屬於左值

初始化時可接受的形式 int && 類型 const int && 類型
int 變量 不可以 不可以
const int 變量 不可以 不可以
int & 變量 不可以 不可以
const int & 變量 不可以 不可以
int && 變量 不可以 不可以
const int && 變量 不可以 不可以
形如 100int 字面常量 可以 可以
形如 1+50*2int 多項表達式 可以 可以
返回類型為 int 的函數返回值 可以 可以
形如 100.0 可轉換為 int 的字面常量 可以 可以
形如 1.0+50.0*2.0 可轉換為 int 的多項表達式 可以 可以