天天看點

C++中左值引用和右值引用的差別

01 什麼是左值和右值?

  • 左值: 就是有确定的記憶體位址、有名字的變量,可以被指派,可以在多條語句中使用;
  • 右值: 沒有名字的臨時變量,不能被指派,隻能在一條語句中出現,如:字面常量和臨時變量。

02 如何區分左值與右值?

看能不能對表達式取位址

能否用“取位址&”運算符獲得對象的記憶體位址。
對于臨時對象,它可以存儲于寄存器中,是以是沒辦法用“取位址&”運算符;
對于常量,它可能被編碼到機器指令的“立即數”中,是以是沒辦法用“取位址&”運算符;
這也是C/C++标準的規定。
           

傳回左值的表達式:

傳回左值引用的函數、指派、下标、解引用、前置遞增/遞減運算符

傳回右值的表達式:

傳回非引用類型的函數、算術、關系、位、後置遞增/遞減運算符

舉例:
int a = 5;
int b = 6;
int *ptr = &a; 
vector v1; 
string str1 = "hello " ;
string str2 = "world" ;
const int &m = 1 ;

a+b//臨時對象
a++//右值,是先取出持久對象a的一份拷貝,再使持久對象a的值加1,最後傳回那份拷貝,而那份拷貝是臨時對象(不可以對其取位址),故其是右值。
++a//左值,使持久對象a的值加1,并傳回那個持久對象a本身(可以對其取位址),故其是左值。
v1[0]//調用了重載的[]操作符,而[]操作符傳回的是一個int &,為持久對象(可以對其取位址)是左值。
string("hello")//臨時對象(不可以對其取位址),是右值;
str1+str2//調用了+操作符,而+操作符傳回的是一個string(不可以對其取位址),故其為右值;
str1//左值
*p//左值
           

03 左值引用和右值引用

C++11引入右值引用,c++11中用&表示左值引用,用&&表示右值引用。

int i = 2;//左值
int &a = i; //左值引用

int &&a = 10; //右值引用
           

根據修飾符的不同,左值引用可分為:非const左值、const左值;右值引用可分為:非const右值、const右值。

int i = 10;//非const左值
const int j = 20;

//非const左值引用
int &a = i;//非const左值引用 綁定到 非const左值,編譯通過
int &a = j;//非const左值引用 綁定到 const左值,編譯失敗
int &a = 5;//非const左值引用 綁定到 右值,編譯失敗

//const左值引用
const int &b = i;//const左值引用 綁定到 非const左值,編譯通過
const int &b = j;//const左值引用 綁定到 const左值,編譯通過
const int &b = 5;//const左值引用 綁定到 右值,編譯通過

//非const右值引用
int &&c = 30;//非const右值引用 綁定到 右值,編譯通過
int &&c = i;//非const右值引用 綁定到 非const左值,編譯失敗(不能将一個右值引用綁定到左值上)

//const右值引用
const int &&d = 40;//const右值引用 綁定到 右值,編譯通過
const int &&d = c;//const右值引用 綁定到 非常量右值,編譯通過
           
  • 非常量的左值引用隻能被綁定到非常量左值
  • 非常量的右值引用隻能被綁定到非常量右值

04 總結

  • 非常量左值引用隻能綁定到

    非常量左值

    ,不能綁定到常量左值、非常量右值和常量右值;
  • 常量左值引用可以綁定到

    const左值、非const左值、const右值、非const右值

  • 非const右值引用隻能綁定到

    非const右值

  • const右值引用可綁定到

    const右值和非const右值

參考文檔

繼續閱讀