移动构造函数与拷贝构造函数

一、移动构造函数:

定义:
所谓移动语义,指的就是以移动而非深拷贝的方式初始化含有指针成员的类对象。简单的理解,移动语义指的就是将其他对象(通常是临时对象)拥有的内存资源“移为已用”。

优点:

提高执行效率,减少临时变量资源的申请和释放。

事实上,对于程序执行过程中产生的临时对象,往往只用于传递数据(没有其它的用处),并且会很快会被销毁。因此在使用临时对象初始化新对象时,我们可以将其包含的指针成员指向的内存资源直接移给新对象所有,无需再新拷贝一份,这大大提高了初始化的执行效率。

函数参数:右值引用

非 const 右值引用只能操作右值,程序执行结果中产生的临时对象(例如函数返回值、lambda 表达式等)既无名称也无法获取其存储地址,所以属于右值。

调用时机:

当类中同时包含拷贝构造函数和移动构造函数时,如果使用临时对象初始化当前类的对象,编译器会优先调用移动构造函数来完成此操作。只有当类中没有合适的移动构造函数时,编译器才会退而求其次,调用拷贝构造函数。

在实际开发中,通常在类中自定义移动构造函数的同时,会再为其自定义一个适当的拷贝构造函数,由此当用户利用右值初始化类对象时,会调用移动构造函数;使用左值(非右值)初始化类对象时,会调用拷贝构造函数。

注意事项:

  1. 参数(右值)的符号必须是右值引用符号,即“&&”。
  2. 参数(右值)不可以是常量,因为我们需要修改右值。
  3. 参数(右值)的资源链接和标记必须修改。否则,右值的析构函数就会释放资源。转移到新对象的资源也就无效了。
#include <iostream>
using namespace std;
class demo{ 
public:
    demo():num(new int(0)){ 
        cout<<"construct!"<<endl;
    }


    demo(const demo &d):num(new int(*d.num)){ 
        cout<<"copy construct!"<<endl;
    }
    //添加移动构造函数
    demo(demo &&d):num(d.num){ 
        d.num = NULL;
        cout<<"move construct!"<<endl;
    }
    ~demo(){ 
        cout<<"class destruct!"<<endl;
    }
private:
    int *num;
};
demo get_demo(){ 
    return demo();
}
int main(){ 
    demo a = get_demo();
    return 0;
}


二、移动拷贝构造函数

MyString& operator=(MyString&& str) { 
   std::cout << "Move Assignment is called! source: " << str._data << std::endl;
   if (this != &str) { 
     _len = str._len;
     _data = str._data;
     str._len = 0;
     str._data = NULL;
   }
   return *this;
}
    原文作者:马斯尔果
    原文地址: https://blog.csdn.net/qq_42108501/article/details/114480385
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞