1.49、移动构造和拷贝构造的区别是什么?

参数类型不同

  • • 拷贝构造函数的参数是一个常量左值引用(const T&),用于从已有对象复制数据;
  • • 移动构造函数的参数是右值引用(T&&),用于接管即将销毁的临时对象资源。

资源处理方式不同

  • • 拷贝构造函数会对对象的所有成员进行逐个复制,通常是深拷贝,分配新的内存并复制内容,保证新旧对象互不影响;
  • • 移动构造函数则“窃取”原对象的资源指针(如堆内存指针、文件句柄等),将资源所有权转移给新对象,并将原对象的指针置为nullptr,避免资源重复释放。

调用时机不同

  • • 拷贝构造函数在使用左值对象初始化新对象、传参或返回对象时调用;
  • • 移动构造函数在使用右值(临时对象或通过std::move转为右值的对象)初始化新对象时调用,目的是避免不必要的深拷贝,提高效率。

性能和语义差异

  • • 拷贝构造函数保证对象的完整复制,适用于所有对象类型,但可能带来性能开销;
  • • 移动构造函数适用于拥有可移动资源的对象(如指针、unique_ptr等),通过资源转移显著减少复制开销,提升性能,尤其在临时对象处理和返回值优化中效果明显。

总结来说,移动构造函数是C++11引入的用于优化资源管理和性能的机制,它通过“移动”资源而非“复制”资源,减少了不必要的内存分配和数据复制。拷贝构造函数则是传统的复制机制,保证对象数据的完整性和独立性。两者在设计时需根据对象的资源管理需求和使用场景合理实现和选择。

示例代码:

class MyString {
    char* str;
    size_t len;
public:
    // 拷贝构造函数:深拷贝
    MyString(const MyString& other) {
        len = other.len;
        str = new char[len + 1];
        strcpy(str, other.str);
    }

    // 移动构造函数:资源转移
    MyString(MyString&& other) noexcept {
        str = other.str;
        len = other.len;
        other.str = nullptr;
        other.len = 0;
    }
};

此设计避免了临时对象的深拷贝,提高了程序性能和资源使用效率。
本文首发于【讳疾忌医-note】公众号,未经授权,不得转载。
(加入我的知识星球,免费获取账号,解锁所有文章。)

阅读剩余
THE END