C++ 11新特性之std::move
左值和右值:
在c++中,一个值要么是右值,要么是左值,左值是指表达式结束后依然存在的持久化对象,右值是指表达式结束时就不再存在的临时对象。所有的具名变量或者对象都是左值,而右值不具名。
通常情况下,判断某个表达式是左值还是右值,最常用的有以下 2 种方法。
- 可位于赋值号(=)左侧的表达式就是左值;反之,只能位于赋值号右侧的表达式就是右值。
int a = 5;
5 = a; //错误,5 不能为左值
其中,变量 a 就是一个左值,而字面量 5 就是一个右值。值得一提的是,C++ 中的左值也可以当做右值使用
int b = 10; // b 是一个左值
a = b; // a、b 都是左值,只不过将 b 可以当做右值使用
- 有名称的、可以获取到存储地址的表达式即为左值;反之则是右值。
以上面定义的变量 a、b 为例,a 和 b 是变量名,且通过 &a 和 &b 可以获得他们的存储地址,因此 a 和 b 都是左值;反之,字面量 5、10,它们既没有名称,也无法获取其存储地址(字面量通常存储在寄存器中,或者和代码存储在一起),因此 5、10 都是右值。
C++右值引用
正常情况下只能操作 C++ 中的左值,无法对右值添加引用.
int num = 10;
int &b = num; //正确
int &c = 10; //错误
不支持为右值建立非常量左值引用,但允许使用常量左值引用操作右值。也就是说,常量左值引用既可以操作左值,也可以操作右值。
int num = 10;
const int &b = num;
const int &c = 10;
为此,C++11 标准新引入了另一种引用方式,称为右值引用,用 “&&” 表示。
需要注意的,和声明左值引用一样,右值引用也必须立即进行初始化操作,且只能使用右值进行初始化。
int num = 10;
//int && a = num; //右值引用不能初始化为左值
int && a = 10;
和常量左值引用不同的是,右值引用还可以对右值进行修改。
int && a = 10;
a = 100;
cout << a << endl;
移动以后(调用移动函数以后),原来变量s指代的值的所有权转移到了left,这个变量s被改变成了”空值“的状态。
不同的类型”空值“状态不一样,所以不建议继续使用s这个变量了。
std::string s =" hell world";
auto left = std::move(s);
//s被move了,对于string来说被设为了空string。