首页 > 代码库 > C++11移动语义之一(基本概念)
C++11移动语义之一(基本概念)
摘要
移动语义是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版)
C++11移动语义之一(基本概念)