一下是阿鲤对右值引用学习的总结,希望对大家有所帮助
一:移动语义
二:右值引用的概念
三:右值引用的使用
四:完美转发
一:移动语义
在介绍右值引用之前,先让大家看下面这段代码
#include<iostream>
using namespace std;
class ADD
{
int m_left;
int m_right;
public:
ADD(int left, int right):
m_left(left),
m_right(right)
{}
ADD(const ADD &add)
{
m_left = add.m_left;
m_right = add.m_right;
}
};
ADD getADD(int a, int b)
{
ADD tmp(a,b);
return tmp;
}
int main()
{
ADD add(getADD(8,8));
return 0;
}
大家猜一猜这段代码执行了几次拷贝构造函数,构造函数,析构函数。详情如下
我们发现的是,就这样一个函数调用竟然调用了一次构造函数,两次拷贝构造,两次析构,这么多次的函数调用无疑会增加时间上的开销,所以有可以直接将临时对象的资源移动到目标对象中的方法,这称之为移动语义。而实现移动语义就要使用右值引用。
这就引出了我们要介绍的右值引用了
二:右值引用的概念:
什么是右值:在c++11中右值分为两个概念,纯右值和将亡值
纯右值:纯右值是c++98中的概念,用于识别临时变量和一些不跟对象关联的值。比如常量,运算表
将亡值:生命周期将要结束的对象
其实只要是不能取地址的值就是就是右值。
右值引用:类型&& 引用变量名字 = 实体
三:右值引用的使用
1:与移动语义配合,减少性能开销
eg:
ADD&& getADD(int a, int b)
{
ADD tmp(a,b);
cout << "&tmp = " << &tmp << endl;
return static_cast<ADD &&>(tmp);//retur move(ADD);
}
int main()
{
ADD &&add(getADD(8,8));
cout << "&add = " << &add << endl;
system("pause");
return 0;
}
运行结果:
结果显示tmp和add就是一个对象,这就是我们借助右值引用实现移动语义的方法
注:系统提供move(),将一个左值强制转换为右值,二static_cast就是其的底层结构。
2:新的默认函数——移动构造函数
比如在string类中的移动构造函数应该是这样的
String(String &&s) :
m_data(move(s.m_data))//使得赋值也调用移动构造,速度更快
{
s.m_data = nullptr;
}
在使用常量例如string s("BelongAi") 这样就会调用移动构造函数(移动构造存在的情况)这样就可以很大的提成程序的性能(移动构造浅拷贝)
注意:
1:c++11中默认提供的移动构造函数和默认拷贝构造是相同的,只会进行浅拷贝而不会进行置空操作,容易造成二次释放,所以要使用移动构造函数时,最好自己实现一个。
2:若将移动构造函数的返回值或参数设置为常右值引用会导致移动语义无法实现
四:完美转发
概念:所谓完美是指函数模板在向其他函数传递自身形参时,如果相应实参是左值,它就应该被转发成左值;如果相应参数是右值,他就应该被转发成右值。
目的:针对左右值的不同会进行不同的处理
实现:在实现之前,先向大家介绍引用折叠,
引用折叠:eg:int && && eque int && int && & / int & && eque int &
#include<iostream>
using namespace std;
//process通过重载实现完美接收
void process(int && t)
{
cout << "process(int &&) : " << t << endl;
}
void proceee(int &t)
{
cout << "process(int &) : " << t << endl;
}
//使用通用引用实现完美转发
template<typename T>
void myforward(T && t)
{
cout << "myforeard : " << t <<endl;
process(forward<T>(t));//系统提供forward来实现完美转发,底层为static_cast<T &&>
}
int main()
{
int a = 2;
myforward(a);//左值
myforward(6);//右值
myforward(move(a));//右值
system("pause");
return 0;
}