摘要
移動語義是C++11的新特性之一,利用移動語義可以實現對象的移動而非拷貝。在某些情況下,可以大幅度的提升性能。本文將介紹C++11移動語義中的一些基本概念。
表達式
表達式是由一個或者多個運算對象組成,對表達式求值將得到一個結果,字面值和變量是最簡單的表達式,其結果就是字面值和變量的值。把一個運算符和一個或者多個運算對象組合起來可以生成較為復雜的表達式。
左值和右值
左值:能夠取得地址的表達式是左值。例如:常見的變量都是左值。又例如一般情況下的賦值表達式是左值(所以一般要求類中重載的賦值操作符要返回*this)。
右值:不能取地址的表達式是右值。例如函數的非引用返回值或者字面常量。(可以簡單的理解,右值是沒有名字,但是又確實被創建的臨時變量)。
class A { }; //a為左值 A a; //getA函數返回右值 A getA() { return A(); } void setA(A a) { } //實參A()為右值 setA(A())
右值引用
引用:變量的別名。有以下要點:1)對引用的操作與對變量的操作是完全一樣的;2)定義引用的時候必須進行初始化,而且不能綁定到其他對象上去。
左值引用:常規引用,只能綁定到左值上(有的編譯器可以綁定到右值,見下文例子)。
右值引用:必須綁定到右值的引用。由於右值通常是被臨時創建、即將被銷毀的對象,所以右值引用可以延長右值的生命周期,直到右值引用類型的變量超出作用域,右值引用類型的變量在銷毀的同時,被引用的右值也一並銷毀。
這里請注意:變量的類型和變量本身是左值還是右值沒有關系(只要是變量,就都是左值,因為其有名字,可以取地址。)例如:不能將右值引用綁定到右值引用類型的變量,這很奇怪,但是實際確實如此:
//a為右值引用類型的變量 A&& a = getA(); //錯誤,a為左值,不能將左值綁定到右值引用上 A&& b = a;
上文提到有的編譯器可以將右值綁定到左值引用上面,在vs2015中,
//vs2015中沒有報錯,將右值綁定到左值引用上面 A& a = getA();
在g++5.3.1,上述代碼會報錯,不能將右值綁定到左值引用上面。
可見,對於右值綁定到左值引用上面,不同的編譯器的要求是不一樣的,可以不必過分關注這些細節問題。右值最重要的使用場景是對象的移動,接下來的文章會進行介紹。
參考
C++ Primer(第5版)