引用
引用常说的是“左值引用”,C++11
中新增了一种引用,即“右值引用”。
左值引用
引用为对象起了另外一个名字,引用必须初始化。
1 | int ival = 1024; |
因为,一般在初始化时,初始值会被拷贝到新建的对象中。然而定义引用时,程序把引用和它的初始值绑定在一起,而不是将初始值拷贝给引用。 一但初始值完成,引用将和它的初始值对象一直绑定在一起。因为无法令引用重新绑定到另一个对象,因此引用必须初始化。
引用即别名:
1 |
|
输出: > ival = 2
> refVal = 2
我们更改引用refVal
的值,发现ival
的值也发生了改变,这正是因为引用只是原来对象的别名。
引用的定义:
允许一条语句中定义多个引用,其中每个引用标识符都必须以字符&
开头。
引用只能绑定在对象上。
1 | int &refVal4 = 10; // 错误:引用类型的初始值必须是一个对象 |
右值引用(rvalue reference)
为了支持移动操作,新标准引入了一种新的引用类型----右值引用。
所谓右值引用就是必须绑定到右值的引用,我们通过&&
而不是&
来获得右值引用。
右值引用只能绑定到一个将要销毁的对象。
一般而言,一个左值表达式表示的是一个对象的身份,而一个右值表达式表示的是对象的值。
1 | int i = 42; |
返回左值的函数,连同赋值,下标,解引用和前置递增/递减运算符,都是返回左值的表达式。 我们可以将一个左值引用绑定到这类表达式的结果上。
返回非引用类型的函数,连同算术,关系,位以及后置递增/递减运算符,都生成右值。
我们可以将一个const
的左值引用或一个右值引用绑定到这类表达式上。
左值持久。右值短暂
左值有持久的状态,而右值要么是字面常量,要么是在表达式求值过程中创建的临时对象。
变量是左值
变量可以看作只有一个运算对象而没有运算符的表达式。
1 | int &&rr1 = 42; // 正确:字面常量是右值 |
标准库movw函数
虽然不能将一个右值引用直接绑定到一个左值上,但我们可以显式地将一个左值转换为对应的右值引用类型。我们还可以通过调用一个名为move
的新标准
库函数来获得绑定到左值上的引用。
此函数定义在头文件utility
中。
1 | int &&rr1 = 42; |
move
调用告诉编译器:我们有一个左值,但我们希望像一个右值一样处理它。
调用move
就意味着承诺:除了对rr1
赋值或销毁它外,我们将不再使用它。在调用move
之后,我们不能对移后源对象的值做任何假设。