C++ 右值參照與一級指標

2022-10-11 09:00:26

右值參照用於一級指標,在初始化時等號右邊必須為右值,有以下幾種用法:

//方式一:參照一級指標,常規用法
int a = 5;
int * &&rrpa = &a;       //右值:例子一
int * getPx() { return new int; }
int * &&rrpa = getPx();  //右值:例子二
int * pa = &a;
int * &&rrpa = std::move(pa);//右值:例子三

//方式二:參照指向常數的一級指標,以下幾種為等效表示
int a = 5;
const int * &&rrpac = &a; //方式一
int const * &&rrpac = &a; //方式二

//方式三:參照一級指標的常參照,參照自身為常數
int a = 5;
int * const &&crrpa = &a;

//方式四:參照指向常數的一級指標,且參照自身為常數,以下幾種為等效表示
int a = 5;
const int * const &&crrpac = &a; //方式一
int const * const &&crrpac = &a; //方式二

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 *&& 等效。

各型別參照可修改屬性如下表所示:

參照型別 修改 *rrp 修改 rrp
int * &&rrp 可以 可以
const int * &&rrp 不可以 可以
int * const &&rrp 可以 不可以
const int * const &&rrp 不可以 不可以

若將變數的地址賦予參照(例如 rrp=&x),各型別參照可接受的變數地址如下表所示:

參照型別 int變數地址 const int變數地址
int * &&rrp 可以 不可以
const int * &&rrp 可以 可以
int * const &&rrp 宣告時可以 不可以
const int * const &&rrp 宣告時可以 宣告時可以

若將函數返回的一級指標值賦予參照(例如 rrp=getPx()),或者使用形如 rrp=(const int *) &x 的強制型別轉換,此時各型別參照可接受的型別如下表所示:

參照型別 int * const int * int * const const int * const
int * &&rrp 可以 不可以 可以 不可以
const int * &&rrp 可以 可以 可以 可以
int * const &&rrp 宣告時可以 不可以 宣告時可以 不可以
const int * const &&rrp 宣告時可以 宣告時可以 宣告時可以 宣告時可以

由於右值參照變數自身為左值,因此不能直接將右值參照變數的值賦予另一個右值參照變數,但可以將函數返回的右值參照值賦予另一個右值參照變數(例如 rrp=getRRPx()),也可以使用 std::move() 將左值轉換為右值(例如 rrp=std::move(px)),此時各型別參照可接受的型別如下表所示。比較上下兩表可知,它們的差別主要在於最後兩列,這是因為 int * constconst int * const 中右邊的 const 修飾的是一級指標自身,而 int * const &&const int * const && 中右邊的 const 修飾的是右值參照自身,代表的含義不同。

參照型別 int * && const int * && int * const && const int * const &&
int * &&rrp 可以 不可以 不可以 不可以
const int * &&rrp 可以 可以 不可以 不可以
int * const &&rrp 宣告時可以 不可以 宣告時可以 不可以
const int * const &&rrp 宣告時可以 宣告時可以 宣告時可以 宣告時可以

右值參照在宣告時是否會建立臨時變數,這與具體應用場景有關,可在編譯後檢視對應的組合程式碼,也可參考本人另一篇部落格 C++ 右值參照與 const 關鍵字。關於左值參照與一級指標,可參考本人另一篇部落格 C++ 左值參照與一級指標