C++复习之(右值引用+转移语义+完美转发)
1. 为什么要右值引用?
当遇到这种情况:
查看代码
class demo{
public:
demo():num(new int(0)){}
demo(const demo &d):num(new int(*d.num)){}
~demo(){}
private:
int *num;
};
demo get_demo(){
return demo();
}
int main(){
demo a = get_demo();
return 0;
}
代码首先执行get_demo() 函数内部的 demo() 语句,调用 demo 类的默认构造函数生成一个匿名对象(第一次默认构造);执行 return demo() 语句,会调用拷贝构造函数复制一份之前生成的匿名对象(第二次拷贝构造),并将其作为 get_demo() 函数的返回值;执行 a = get_demo() 语句,再调用一次拷贝构造函数(第三次拷贝构造),将之前拷贝得到的临时对象复制给 a;可以发现后面两次构造都是浪费的,因此有了移动构造函数。
查看代码
class demo{
public:
demo():num(new int(0)){}
demo(const demo &d):num(new int(*d.num)){}
demo(demo &&d):num(d.num){
d.num = NULL;
}
~demo(){}
private:
int *num;
};
demo get_demo(){
return demo();
}
int main(){
demo a = get_demo();
return 0;
}
该函数使用右值引用形式的参数,并且在此构造函数中,num 指针变量采用的是浅拷贝的复制方式,同时在函数内部重置了原来的d.num,相当于直接将原来的空间的内容直接给新建的内使用,省去了重新分配空间和赋值的问题,节省开销。
2. 什么是右值引用?
左值指可以找到地址空间的值,右值指没法找到地址空间的值,比如常数表达式。右值引用就是右值的引用,用&&表示。
引用折叠,A& && = A&;A& & = A&;A&& & = A&;
A && && = A &&;
3. 转移语义
移动构造函数就是转移语义的体现,对于实际使用中,我们想要左值也能使用转移语义,使用move()函数,move()函数可以将左值类型转为右值。
4.完美转发
完美转发就是创建一个函数,该函数可以接收任意类型的参数,然后将这些参数按原来的类型转发给目标函数,完美转发的实现要依靠std::forward函数。就是说,输入的参数类型是左值,转发过去也是左值,是右值转发过去也是右值。
查看代码
template <typename T>
void function(T&& t) {
otherdef(t);
}
int n = 10;
int & num = n;
function(num); // T 为 int&
int && num2 = 11;
function(num2); // T 为 int &&
浙公网安备 33010602011771号