C++ 拷贝构造函数、移动构造函数以及用法

在C++中,拷贝构造函数和移动构造函数都是构造函数的特殊形式,用于创建类对象的副本或转移对象的资源。这两者的用法和目的不同,各有其使用场景。

1. 拷贝构造函数

拷贝构造函数用于创建一个对象的副本,复制对象的成员数据。

语法
class MyClass {
public:
    MyClass(const MyClass& other); // 拷贝构造函数的声明
};
默认拷贝构造函数

如果类没有显式定义拷贝构造函数,编译器会自动生成一个默认的拷贝构造函数。默认的拷贝构造函数会逐个复制对象的每个成员,称为“浅拷贝”。

自定义拷贝构造函数

在某些情况下,如类中有指针成员或需要深拷贝时,需要自定义拷贝构造函数:

class MyClass {
    int* data;
public:
    MyClass(int val) : data(new int(val)) {}

    // 自定义拷贝构造函数,执行深拷贝
    MyClass(const MyClass& other) {
        data = new int(*other.data); // 分配新内存并复制值
    }

    ~MyClass() {
        delete data;
    }
};
使用场景

当一个对象需要被复制时,会调用拷贝构造函数,例如:

  • 对象传递到函数时按值传递
  • 对象从函数返回时按值返回
  • 用一个对象初始化另一个对象时
MyClass obj1(5);
MyClass obj2 = obj1; // 调用拷贝构造函数

2. 移动构造函数

移动构造函数在C++11中引入,用于高效地“移动”对象的资源,而不是复制。它避免了不必要的资源分配和数据复制,特别适合处理临时对象或大数据对象。

语法
class MyClass {
public:
    MyClass(MyClass&& other); // 移动构造函数的声明
};
默认移动构造函数

如果类没有定义移动构造函数,编译器会在可能的情况下自动生成默认的移动构造函数。默认移动构造函数执行成员的“移动”,通常是浅移动(将指针或资源的所有权转移)。

自定义移动构造函数

如果类中有动态分配的资源(如指针),可能需要自定义移动构造函数,以避免重复释放资源。

class MyClass {
    int* data;
public:
    MyClass(int val) : data(new int(val)) {}

    // 自定义移动构造函数
    MyClass(MyClass&& other) noexcept {
        data = other.data;   // 转移资源的所有权
        other.data = nullptr; // 避免原对象释放资源
    }

    ~MyClass() {
        delete data;
    }
};
使用场景

移动构造函数在以下场景下会被调用:

  • 将一个临时对象赋给另一个对象时
  • 通过 std::move 将一个对象显式地转换为右值引用
  • 从函数返回一个对象时
MyClass obj1(5);
MyClass obj2 = std::move(obj1); // 调用移动构造函数

3. 区别与用法

拷贝构造 vs 移动构造
  • 拷贝构造会深度复制对象的所有成员变量,适用于要创建对象副本的场景。
  • 移动构造会将资源从一个对象转移到另一个对象,而不是复制,避免了深拷贝的性能开销。
拷贝构造的典型场景:
  • 当你需要保留源对象并同时创建一个新对象时,例如函数按值传递、按值返回。
  • 适用于类中成员变量不涉及资源管理(如指针、动态内存)时。
移动构造的典型场景:
  • 处理临时对象时,临时对象只需短期使用,然后资源可以转移。
  • 用于大数据对象的转移操作(如容器、文件句柄等),避免不必要的资源分配。
举例

拷贝构造函数:

MyClass obj1(10);  // 普通构造
MyClass obj2(obj1); // 拷贝构造,obj2 是 obj1 的副本

移动构造函数:

MyClass obj1(10); 
MyClass obj2(std::move(obj1)); // 移动构造,obj2 拥有 obj1 的资源,obj1 被置为空

4. 拷贝/移动构造函数的选择顺序

编译器会根据以下优先级选择构造函数:

  1. 如果能移动,编译器优先使用移动构造函数
  2. 如果不能移动(如对象为const或没有移动构造函数),则使用拷贝构造函数

5. 总结

  • 拷贝构造函数用于创建对象的副本,通常涉及深拷贝的情形。
  • 移动构造函数则用于转移资源,避免了不必要的深拷贝,提高了性能。
  • 在资源管理类中,通常需要同时定义拷贝构造函数、移动构造函数,以及相应的析构函数来确保资源的正确管理
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值