右值引用
内容源自C++ Primer第五版13.6.1
为了支持移动操作,C++新标准引入了一种新的引用类型——右值引用。所谓右值引用就是必须绑定到右值的引用。
我们通过&&
而不是&
来获得右值引用。右值引用有一个重要的性质——只能绑定到一个将要销毁的对象。因此,我们可以自由地将一个右值引用的资源“移动”到另一个对象中。
一般而言,一个左值表达式表示的是一个对象的身份,而一个右值表达式表示的是对象的值。
类似任何引用,一个右值引用也不过是某个对象的另一个名字而已。对于常规的左值引用,我们不能将其绑定到要求转换的表达式、字面常量或是返回右值的表达式。右值引用有着完全相反的绑定特性:我们可以将一个右值引用绑定到这类表达式上,但不能将一个右值引用直接绑定到一个左值上。
int i = 42; //
int &r = i; // 正确:r引用i
int &&rr = i; // 错误:不能将一个右值引用绑定到一个左值上。
int &r2 = i * 42; // 错误:i*42是一个右值
const int &r3 = i *42; // 正确:可以将一个const的引用绑定到一个右值上
int &&rr2 = i * 42; // 正确:将rr2绑定到乘法结果上
左值持久;右值短暂
左值有持久的状态,而右值要么是字面常量,要么是表达式求值过程中创建的临时对象。
由于右值引用只能绑定到临时对象,我们得知:
- 所引用的对象将要被销毁
- 该对象没有其他用户(?)
这两个特性意味着:使用右值引用的代码可以自由地接管所引用对象的资源。
变量是左值
变量是左值,因此我们不能将一个右值引用直接绑定到一个变量上,即使这个变量是右值引用类型也不行。
int &&rr1 = 42; // 正确:字面常量是右值
int &&rr2 = rr1; // 错误:rr1是左值
标准库move函数
可以通过调用一个名为move
的新标准库函数来获得绑定到左值上的右值引用,即可以显式的将一个左值转换为对应的右值引用类型。
int &&rr1 = 42; // 正确:字面常量是右值
int &&rr2 = rr1; // 错误:rr1是左值
int &&rr3 = std::move(rr1); // 正确
也就意味着对编译器承诺:除了对rr1赋值或销毁它外,我们将不再使用它的值。