C++深拷贝与浅拷贝

拷贝构造函数 vs 赋值运算符重载

  1. 拷贝构造函数

    • 情景:当新对象被创建时,用一个已有对象初始化新对象。
    • 用途:复制对象时调用(例如通过拷贝构造函数传递对象或返回对象)。
    • 问题:如果默认的拷贝构造函数执行浅拷贝,新对象的指针将指向相同的内存区域,导致两个对象共享同一块内存。
  2. 赋值运算符重载

    • 情景:当一个已有对象被赋值给另一个已有对象时。
    • 用途:赋值操作(例如 obj2 = obj1)。
    • 问题:如果默认的赋值运算符执行浅拷贝,被赋值对象的指针将指向赋值对象的内存区域,导致两个对象共享同一块内存。

情景1:拷贝构造函数

class MyClass 
{
public:
    int* data;
    int size;

    MyClass(int s) : size(s) 
    {
        data = new int[size];
    }

    ~MyClass() 
    {
        delete[] data;
    }

    // 拷贝构造函数
    MyClass(const MyClass& other) 
    {
        size = other.size;
        data = new int[size];
        for (int i = 0; i < size; ++i)  
        {
            data[i] = other.data[i];
        }
    }
};

int main() 
{
    MyClass obj1(10);
    MyClass obj2 = obj1;  // 调用拷贝构造函数
}

在这个例子中,obj2 是通过拷贝构造函数创建的。如果没有深拷贝(如上述实现),obj2obj1 将共享同一个内存区域。这种情况拷贝构造函数解决了。

情景2:赋值操作符重载

class MyClass 
{
public:
    int* data;
    int size;

    MyClass(int s) : size(s) 
    {
        data = new int[size];
    }

    ~MyClass() 
    {
        delete[] data;
    }

    // 拷贝构造函数
    MyClass(const MyClass& other) 
    {
        size = other.size;
        data = new int[size];
        for (int i = 0; i < size; ++i)
        {
            data[i] = other.data[i];
        }
    }

    // 赋值操作符重载
    MyClass& operator=(const MyClass& other) 
{
        if (this == &other)  
        {
            return *this;  // 防止自赋值
        }

        // 释放旧的内存
        delete[] data;

        // 分配新内存并复制数据
        size = other.size;
        data = new int[size];
        for (int i = 0; i < size; ++i) 
        {
            data[i] = other.data[i];
        }

        return *this;
    }
};

int main() 
{
    MyClass obj1(10);
    MyClass obj2(20);
    obj2 = obj1;  // 调用赋值操作符重载
}

在这个例子中,obj2 是在已经存在时被赋值的。如果没有深拷贝,obj2obj1 将共享同一个内存区域。这种情况下赋值操作符重载解决了。

这两个问题虽然看起来类似,但发生在不同的对象生命周期阶段,因此需要分别处理。拷贝构造函数用于对象初始化阶段,而赋值操作符重载用于对象赋值阶段。两者结合,确保了对象在任何情况下都能正确地进行深拷贝,避免共享内存带来的问题。

如果在情景二中删除拷贝构造函数,但保留赋值操作符重载,那么编译器将生成默认的拷贝构造函数。默认的拷贝构造函数执行浅拷贝,而重载的赋值操作符将执行深拷贝。在这种情况下,赋值操作不会有问题,但在需要拷贝构造的情景中仍会出现浅拷贝问题。比如在情景二中删除拷贝构造函数,

int main() 
{
    MyClass obj1(10);
    MyClass obj2 = obj1;  // 调用默认的拷贝构造函数(浅拷贝)
}

就无法处理浅拷贝带来的问题了。

  • 6
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值