目录
一、左值引用和右值引用
1.什么是左值?什么是左值引用?
2.什么是右值?什么是右值引用?
3.左值引用与右值引用比较
二、右值引用使用场景和意义
1.左值引用的使用场景
2.左值引用的短板:
3.右值引用和移动语义解决上述问题
移动构造:
移动赋值:
三、右值引用引用左值及其一些更深入的使用场景分析
无论左值引用还是右值引用,都是给对象取别名。
注意事项:
1.凡是能放在等式左边的一定是左值!!!
2.右值本身不能被修改,但是右值被右值引用后就变为了左值,需要被修改,否则无法实现移动构造和移动赋值(因为这两个操作的本质就是转移资源,我如果不是左值,怎么转移?)
eg:int&& x = 10;10是右值,但是x是左值,x是对10的右值引用
1. 左值引用只能引用左值,不能引用右值。2. 但是const左值引用既可引用左值,也可引用右值
1. 右值引用只能右值,不能引用左值。2. 但是右值引用可以move以后的左值。
①作为函数参数来引用传参 例如:void func(const T&x)
②接收函数返回值来引用返回
(部分场景适用:出了函数作用域,返回对象的生命周期还没结束)
例如:自定义类的运算符重构时
string& operator+=(char ch)
可以引用返回,避免深拷贝带来的消耗
为了避免出现类似多次调用深拷贝的情况,C++11在这里就提出了右值引用与移动语义来解决这个问题
移动构造本质是将参数右值的资源窃取过来,占位已有,那么就不用做深拷贝了,所以它叫做移动构造,就是窃取别人的资源来构造自己。
在bit::string类中增加移动赋值函数,再去调用bit::to_string(1234),不过这次是将bit::to_string(1234)返回的右值对象赋值给ret1对象,这时调用的是移动构造。
这里运行后,我们看到调用了一次移动构造和一次移动赋值。因为如果是用一个已经存在的对象接收,编译器就没办法优化了。bit::to_string函数中会先用str生成构造生成一个临时对象,但是我们可以看到,编译器很聪明的在这里把str识别成了右值,调用了移动构造。然后在把这个临时对象做为bit::to_string函数调用的返回值赋值给ret1,这里调用的移动赋值。
按照语法,右值引用只能引用右值,但右值引用一定不能引用左值吗?因为:有些场景下,可能真的需要用右值去引用左值实现移动语义。当需要用右值引用引用一个左值时,可以通过move 函数将左值转化为右值。C++11中,std::move()函数位于 头文件中,该函数名字具有迷惑性,它并不搬移任何东西, 唯一的功能就是将一个左值强制转化为右值引用,然后实现移动语义 。