c++中的拷贝构造函数(深拷贝和浅拷贝)

在C++中,浅拷贝(Shallow Copy)和深拷贝(Deep Copy)是对象复制的两种不同方式,它们的核心区别在于如何处理对象内部的动态资源管理(如指针、文件句柄等)。


一、浅拷贝(Shallow Copy)

定义
浅拷贝仅复制对象的成员值(包括指针的值),但不复制指针指向的实际内容。拷贝后的对象和原对象会共享同一块动态分配的内存。

特点

  1. 默认行为:C++默认的拷贝构造函数和拷贝赋值运算符是浅拷贝。
  2. 速度快:仅复制指针地址,不复制实际数据。
  3. 风险高:如果多个对象共享同一块内存,可能导致双重释放(double-free)或悬空指针(dangling pointer)。

示例

class ShallowString {
public:
    char* data;
    // 构造函数
    ShallowString(const char* s) {
        data = new char[strlen(s) + 1];
        strcpy(data, s);
    }
    // 默认拷贝构造函数是浅拷贝:ShallowString(const ShallowString& other) : data(other.data) {}
};

int main() {
    ShallowString s1("Hello");
    ShallowString s2 = s1;  // 浅拷贝:s2.data 和 s1.data 指向同一内存
    delete s1.data;         // s2.data 现在指向已释放的内存(悬空指针)
}

 


二、深拷贝(Deep Copy)

定义
深拷贝会复制对象的所有内容,包括指针指向的动态分配资源。拷贝后的对象和原对象拥有独立的资源副本。

特点

  1. 安全性高:每个对象管理自己的资源,避免共享内存问题。
  2. 需手动实现:需要自定义拷贝构造函数、拷贝赋值运算符和析构函数(遵循 Rule of Three)。
  3. 性能开销:复制大量数据时可能较慢。

示例

class DeepString {
public:
    char* data;
    // 构造函数
    DeepString(const char* s) {
        data = new char[strlen(s) + 1];
        strcpy(data, s);
    }
    // 深拷贝构造函数
    DeepString(const DeepString& other) {
        data = new char[strlen(other.data) + 1];
        strcpy(data, other.data);
    }
    // 深拷贝赋值运算符
    DeepString& operator=(const DeepString& other) {
        if (this != &other) {  // 防止自赋值
            delete[] data;     // 释放旧资源
            data = new char[strlen(other.data) + 1];
            strcpy(data, other.data);
        }
        return *this;
    }
    // 析构函数
    ~DeepString() {
        delete[] data;
    }
};

int main() {
    DeepString s1("World");
    DeepString s2 = s1;  // 深拷贝:s2.data 是独立副本
    delete s1.data;      // 不影响 s2.data
}

 


三、关键区别

特性浅拷贝深拷贝
复制内容仅复制指针地址复制指针指向的实际数据
资源所有权共享资源独立资源
默认行为否(需手动实现)
性能快(仅复制指针)慢(复制数据)
安全性低(可能双重释放)

四、何时需要深拷贝?

当类满足以下条件时,必须实现深拷贝:

  1. 包含动态分配的资源(如 new 分配的指针)。
  2. 需要确保对象的独立性(避免共享资源导致的副作用)。

五、现代C++的替代方案

  1. 使用智能指针(如 std::unique_ptrstd::shared_ptr)自动管理资源。
  2. 遵循 Rule of Zero:通过依赖智能指针等工具,避免手动实现拷贝控制函数。
#include <memory>
class SafeString {
    std::unique_ptr<char[]> data;  // 自动管理资源
public:
    SafeString(const char* s) : data(std::make_unique<char[]>(strlen(s) + 1)) {
        strcpy(data.get(), s);
    }
    // 无需手动实现拷贝构造函数、赋值运算符和析构函数!
};

 


总结

  • 浅拷贝适合无动态资源的简单对象(如仅包含基本类型的类)。
  • 深拷贝是管理动态资源时的必要手段。
  • 现代C++中,优先使用智能指针和RAII(Resource Acquisition Is Initialization)来避免手动深拷贝。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值