~May~ 发表于 5 天前

面向对象-深拷贝与浅拷贝

#include <iostream>

using namespace std;

// 浅拷贝:在拷贝构造函数中,直接完成属性的值拷贝操作(默认的拷贝构造函数)
// 深拷贝:在拷贝构造函数中,开辟一块新的区域,让属性的指针指向一块新的空间

class Cat {
public:
        string name;
        int age;
};

class Person {
public:
        int        age;
        Cat* pet;

        Person() {
                age = 0;
                pet = new Cat();
        }

        // 拷贝构造函数
        Person(const Person& p) {
                // 默认的拷贝构造函数的实现,就是浅拷贝,直接完成值的拷贝操作
                age = p.age;
                // pet = p.pet;// 浅拷贝会导致析构函数执行之后xiaobai的pet无法释放,会报错
                pet = new Cat;
                pet->name = p.pet->name;
                pet->age = p.pet->age;
        }

        ~Person() {
                if (pet!=nullptr)
                {
                        delete pet;
                        pet = nullptr;
                }
        }
};
int main() {

        Person xiaobai;
        Person xiaohei = xiaobai;

        return 0;
}

FishC 发表于 5 天前

你给出的代码演示了深拷贝和浅拷贝的区别。在面向对象编程中,深拷贝和浅拷贝是两个重要的概念,尤其在涉及动态内存分配时。

浅拷贝与深拷贝的区别


[*]浅拷贝: 复制对象时只复制对象的基本数据类型成员,对于指针成员,拷贝的是指针的地址。这意味着多个对象可能指向同一个内存地址。
[*]深拷贝: 除了复制对象的基本数据类型成员,还会为指针成员分配新的内存空间,并复制内容。这确保每个对象都有自己独立的内存空间。


在你的代码中,`Person`类的拷贝构造函数通过 new Cat 为指针成员 pet 分配新的内存空间,从而实现了深拷贝。这样,当对象被销毁时,每个对象可以安全地释放其各自的资源,避免了因多次释放同一块内存而导致的错误。

以下是代码中的关键部分解释:


Person(const Person& p) {
    age = p.age;
    pet = new Cat;// 为新对象分配新的内存空间
    pet->name = p.pet->name;// 复制具体内容
    pet->age = p.pet->age;
}


通过这种方式,当 Person xiaohei = xiaobai; 执行时,xiaohei 拥有自己独立的 Cat* pet 实例,而不是与 xiaobai 共享。

这样设计确保了在析构函数中,内存能够被正确释放:


~Person() {
    if (pet != nullptr) {
      delete pet;
      pet = nullptr;
    }
}


如果有任何其他问题,随时提出!

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
页: [1]
查看完整版本: 面向对象-深拷贝与浅拷贝