本文内容:
- 什么是右值引用,与左值引用的区别?
- 什么是移动语义?
- 如何实现移动语义?
- move和forward函数的作用
右值引用
右值:临时对象,无名,不能对它使用取地址符
常见类型:字面量、表达式、返回值的函数
右值引用:右值引用导致右值被存储到特定位置,且可以获取地址(引用C++ Primer Plus)
与左值引用的区别?
左值 右值 意义 有名对象 临时对象 取地址 可用取地址符&获取地址 不可 常见类型 字面量、表达式、返回值的函数 声明引用 & && 用处 实现移动语义,减少内存复制
移动语义
vector<string> method1(const vector<string>& V){ vector<string> V1; //V1是对V处理后得到的 return V1; } int main(){ vector<string> V; //给V填充内容 vector<string> V2 = method1(V); }
编译器会把V1复制给临时返回对象,把临时返回对象复制给V2,再把临时返回对象销毁,移动语义直接把临时对象的数据访问权给V2,从而避免内存中数据复制
就像电脑中文件的移动其实只是修改了记录,文件还是在硬盘中的同一个地方
实现移动语义
- 提供移动构造、赋值函数(转移数据),参数是右值,以区分复制构造、赋值函数
- 通过传递右值(表达式)来调用
using namespace std; class TestClass{ TestClass(const TestClass &t){ } TestClass(TestClass &&t){ } }; int main(){ TestClass t1,t2; TestClass t3 = t1;//调用拷贝构造 TestClass t4 = t1+t2;//调用移动构造 }
move和forward
- move:有时想对左值进行移动,可以用move将它强制转成右值,从而调用移动
- forward:模板函数中,把模板参数传递给另一个调用函数时,实现完美转发(参数以及左右值类型一起转发),左值->左值、右值->右值
- 函数模板的参数类型为 T&&
- forward对传入的参数进行转发
//代码引自http://c.biancheng.net/view/7868.html //重载被调用函数,查看完美转发的效果 void otherdef(int & t) { cout << "lvalue\n"; } void otherdef(const int & t) { cout << "rvalue\n"; } //实现完美转发的函数模板 template <typename T> void function(T&& t) { otherdef(forward<T>(t)); }