C++的深拷贝和浅拷贝


1、浅拷贝(Shallow Copy)

  浅拷贝只复制对象的成员变量的值,如果对象中有指针,浅拷贝会复制指针的值(即地址),而不是指针指向的内容。因此,浅拷贝后,两个对象的指针成员会指向同一块内存。

问题:如果其中一个对象释放了这块内存,另一个对象的指针就会变成悬空指针(dangling pointer),访问它会导致未定义行为。

class ShallowCopy {
public:
    int* data;

    ShallowCopy(int value) {
        data = new int(value);
    }

    ~ShallowCopy() {
        delete data;
    }
};

int main() {
    ShallowCopy obj1(10);
    ShallowCopy obj2 = obj1; // 浅拷贝

    // obj1和obj2的data指针指向同一块内存
    *obj2.data = 20;

    std::cout << *obj1.data << std::endl; // 输出20
    // 当obj1和obj2析构时,会尝试释放同一块内存,导致程序崩溃
}

2、深拷贝(Deep Copy)

  深拷贝不仅复制对象的成员变量,还会为指针成员分配新的内存,并复制指针指向的内容。因此,深拷贝后,两个对象的指针成员指向不同的内存块。

class DeepCopy {
public:
    int* data;

    DeepCopy(int value) {
        data = new int(value);
    }

    // 深拷贝构造函数
    DeepCopy(const DeepCopy& other) {
        data = new int(*other.data); // 分配新内存并复制内容
    }

    // 深拷贝赋值运算符
    DeepCopy& operator=(const DeepCopy& other) {
        if (this == &other) return *this; // 自赋值检查
        delete data; // 释放原有内存
        data = new int(*other.data); // 分配新内存并复制内容
        return *this;
    }

    ~DeepCopy() {
        delete data;
    }
};

int main() {
    DeepCopy obj1(10);
    DeepCopy obj2 = obj1; // 深拷贝

    *obj2.data = 20;

    std::cout << *obj1.data << std::endl; // 输出10
    std::cout << *obj2.data << std::endl; // 输出20
    // obj1和obj2的析构函数不会冲突
}

3.拷贝构造函数

1. 什么是拷贝构造函数?

  拷贝构造函数是C++中的一种特殊构造函数,用于创建一个新对象,并用另一个同类型对象的值来初始化它。它的主要作用是 复制对象。

拷贝构造函数的定义形式如下:

ClassName(const ClassName& other);
  • ClassName 是类的名称。
  • other 是要被复制的对象,通常以 const 引用传递。

2. 拷贝构造函数的调用时机

拷贝构造函数在以下情况下会被调用:

  1. 显式复制对象:
MyClass obj1;
MyClass obj2 = obj1; // 调用拷贝构造函数
  1. 函数传参(按值传递对象):
void func(MyClass obj); // 调用拷贝构造函数
MyClass obj1;
func(obj1); // 传递obj1时,会调用拷贝构造函数

3. 默认拷贝构造函数

如果你没有为类定义拷贝构造函数,C++编译器会自动生成一个 默认拷贝构造函数。默认拷贝构造函数会逐个复制对象的成员变量(浅拷贝)。

class MyClass {
public:
    int value;
    int* ptr;

    MyClass(int v, int p) : value(v), ptr(new int(p)) {}
    ~MyClass() { delete ptr; }
};

int main() {
    MyClass obj1(10, 20);
    MyClass obj2 = obj1; // 默认拷贝构造函数(浅拷贝)

    // obj1和obj2的ptr指向同一块内存
    *obj2.ptr = 30;

    std::cout << *obj1.ptr << std::endl; // 输出30
    // obj1和obj2析构时,会重复释放ptr,导致程序崩溃
}

问题:

默认拷贝构造函数是浅拷贝,如果对象中有指针或动态分配的资源,会导致多个对象共享同一块内存。

析构时可能会重复释放内存,导致程序崩溃。

4. 自定义拷贝构造函数(深拷贝)

为了避免浅拷贝的问题,可以为类定义自定义的拷贝构造函数,实现 深拷贝。

class MyClass {
public:
    int value;
    int* ptr;

    // 普通构造函数
    MyClass(int v, int p) : value(v), ptr(new int(p)) {}

    // 自定义拷贝构造函数(深拷贝)
    MyClass(const MyClass& other) : value(other.value), ptr(new int(*other.ptr)) {}

    // 析构函数
    ~MyClass() { delete ptr; }
};

int main() {
    MyClass obj1(10, 20);
    MyClass obj2 = obj1; // 调用自定义拷贝构造函数(深拷贝)

    *obj2.ptr = 30;

    std::cout << *obj1.ptr << std::endl; // 输出20,obj1的ptr未被修改
    std::cout << *obj2.ptr << std::endl; // 输出30,obj2的ptr被修改

    // obj1和obj2析构时,各自释放自己的内存,不会冲突
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值