????????右值引用就是必须绑定到右值的引用,通过&&而不是&来获得右值引用,右值引用有一个重要的性质,只能绑定到一个将要销毁的对象。
? ? ? ? 首先明确一下,左值和右值是表达式的属性,所有的表达式要么是左值,要么是右值,但是左值可以当作右值使用。左值持久,右值短暂,即左值有持久的状态,而右值要么是字面值常量要么是表达式求值过程中创建的临时量。左值是有名字的对象,可以取地址(这里字符串字面值是个例外,虽然它是左值,但是好像不能取地址),右值是没有名字的对象,也不能取地址,比如各种临时量,除字符串以外的其它字面值等。
? ? ? ? 右值是短暂的临时量,但是可以设法延长其生命周期,一种方法是用常量左值引用来绑定一个右值,另一种就是C++11中引入的右值引用。
![](https://img-blog.csdnimg.cn/20210727223156832.png)
如上图,表达式 i * 42的结果当然是一个临时量,也就是一个右值,所以不能用左值引用来绑定,但是用 const int &r4 = i * 42 是可以的,也就是可以用常量左值引用来绑定一个右值,但是绑定之后就不能更改了。
? ? ? ? 另一个例子是自增自减运算符,比如:
int a = 0, b = 0;
int i = a++;
int j = ++b;
这里 后置自加 a++ 返回的是一个右值,而 ++ b 前置自加返回的是一个左值,但是这里左值当成右值使用了,如果 ++b = 100,这里则是把++b的结果当成左值使用。因此在写for循环的时候 i++ 和 ++i其实效率是略有不同的,i++要先生成一个值等于i的临时量作为表达式结果返回,然后再给i自加,但是++i是直接给i自加的,因此++i的效率会略高一点,但是一般影响不大。
????????综上所述,右值引用的一大目的是减少不必要的拷贝,即将那么马上要销毁的没有名字的临时量给冠名,然后就可以使用这个名字来操作那些原本要销毁的临时量。甚至可以认为,当用右值引用来绑定一个临时量对象以后,这个右值引用变量就相当于原先临时量转换而成的左值。
![](https://img-blog.csdnimg.cn/20210727225314890.png)
由上边例子可以看出,右值引用本身可以看成是一个左值,因此不能用右值引用来绑定一个右值引用。
? ? ? ? 所有的变量(对象)都是左值,可以看成是只有一个运算对象而没有操作符的左值。因为其有生命周期,其状态是持久的,所以都是左值。
? ? ? ? ?虽然一个右值引用不能直接绑定到左值上,但是可以显示地将一个左值转换为对应的右值引用。
![](https://img-blog.csdnimg.cn/20210727225659599.png)
?使用move将左值,即变量rr1转换成右值以后,除了对rr1做销毁或赋值运算以外,将不能够再使用它。注意move函数的使用是直接用std::move,即不用using声明。
|