1. 程式人生 > >右值和左值,右值引用和左值引用

右值和左值,右值引用和左值引用

右值和左值

左值右值的形式區分(或者稱語法區分)是能否用取地址&運算子;語義區分(即其本質涵義)在於表示式代表的是持久物件還是臨時物件。

當一個物件被用作右值的時候,用的是物件的值(內容),當物件被用作左值的時候,用的是物件的身份(在記憶體中的位置) ——CppPrimer, 5th

返回左值的有:

  • 賦值運算子需要一個(非常量)左值作為其左側運算物件,得到的結果也是一個左值
  • 取地址作用於一個左值運算物件,返回一個指向該運算物件的指標, 該指標是一個右值
  • 內建的解引用運算子,下標運算子,迭代器解引用,string 和 vector 的下標運算子,他們的求值結果都是左值
  • 內建型別和迭代器的遞增遞減運算子作用於左值,而前置版本多的結果是左值

右值引用和左值引用

為了支援移動操作,新標準引入右值引用(&&)。右值引用必須繫結到右值,其有一個重要的性質——只能繫結到一個將要銷燬的物件。使用右值引用繫結到一個物件後,可以給該物件賦予新值或者銷燬,但不能再使用它。

int i = 42;            
int &r = i;               //正確:r引用i
int &&rr = i;             //錯誤:不能將一個右值繫結到一個左值上
const int &r3 = i * 42    //正確:我們可以將一個const引用繫結到一個左值
int &&rr2 = i * 42 // 正確:將rr2繫結到乘法結果上

注意 一個變量表達式是左值

int &&rr1 = 42;
int &&rr2 = rr1;    //錯誤,rr1是一個右值引用型別的變數,而變量表達式都是左值

右值特例

在一個物件上呼叫成員函式, 而不管該物件是否是一個左值還是右值

string s1 = "a value", s2 = "another";
auto n = (s1 + s2).find('a');

甚至 s1 + s2 = "wow!";

在新標準中 通過在引數列表後放置一個引用限定符

來限制函式用於左值還是右值

class Foo
{
public:
    Foo &operator=(const Foo&) &;        //只能向可修改的左值賦值
};

Foo &Foo::operator=(const Foo &rhs) &
{
    return *this;
}