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 &&

 

 
posted on 2022-05-12 17:32  俊男  阅读(65)  评论(0)    收藏  举报