右值引用
1. 什么是右值引用
右值引用是C++11新加的一种引用类型,是一种仅能绑定到右值上的引用。不同于左值引用仅用一个&表示,右值引用用两个&&表示。
1 | int x{ 5 }; |
右值引用有两个非常有用的性质: 1. 右值引用将初始化他们的对象的寿命延长到右值引用的寿命;2. 非常量的右值引用允许修改右值。
看一个实际例子:
1 |
|
这段代码打印出:
1 | 3/5 |
Fraction{ 3, 5 }是一个匿名对象(临时对象),在这行语句结束的时候就出了作用域,本来应该被销毁掉,但是我们用了一个右值引用来绑定它,因此延长了它的生命期,直到main函数结束,局部变量rref被销毁的时候,这个临时对象才会被销毁。
再看另外一个例子:
1 |
|
这段代码执行结果是:
1 | 10 |
这里用字面值初始化一个右值引用,会创建一个临时对象,我们可以通过右值引用来修改这个对象。
2. 右值引用作为函数参数
右值引用最有用的地方在于作为函数参数,尤其是在写重载函数时,希望对传入的左值和右值表现出不同的行为。
1 | void fun(const int& lref) |
这段代码打印出:
1 | l-value reference to const. |
可以看出,当传入的参数是左值时,调用的是左值版本的fun(), 当传入的参数是右值时,调用的是右值版本的fun()。可是这有什么用呢?这对于移动语义来说是一个非常重要的特性,后面会继续讨论。
再看一个有意思的例子:
1 | int &&ref{ 5 }; |
ref是一个右值引用,那么fun(ref)调用的是右值引用版本吗?事实上,这里调用的是左值版本的fun()函数。虽然ref是一个右值引用,但是这仅说明它绑定的对象是一个右值,它本身是一个局部变量,是一个左值,因此这行代码调用的是左值版本的fun()。
3. 不要返回右值引用
在绝大多数情况下,你都不应该返回右值引用。因为右值引用绑定的对象在出作用域之后就会被销毁,因此从函数返回,你智能得到一个”hanging reference”。
参考资料
[1].https://www.learncpp.com/cpp-tutorial/15-2-rvalue-references/