面试题:C++ 中什么是深拷贝?什么是浅拷贝?写一个标准的拷贝构造函数?

在C++中,拷贝是指用一个对象初始化另一个对象。拷贝分为深拷贝(Deep Copy)和浅拷贝(Shallow Copy),它们的区别在于如何处理指针或动态分配的资源。


1. 浅拷贝(Shallow Copy)

  • 定义:浅拷贝只是简单地复制对象的成员变量的值,包括指针的值(即地址),而不会复制指针所指向的内容。
  • 问题
    • 如果对象中有指针成员,浅拷贝会导致两个对象的指针指向同一块内存。
    • 当其中一个对象释放内存时,另一个对象的指针会成为悬空指针(Dangling Pointer),导致未定义行为。
    • 多次释放同一块内存会导致程序崩溃。

示例:

class ShallowCopy {
private:
    int* data;

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

    ~ShallowCopy() {
        delete data;
    }

    void print() const {
        std::cout << "Value: " << *data << std::endl;
    }
};

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

    obj1.print(); // 输出: Value: 10
    obj2.print(); // 输出: Value: 10

    // obj1 和 obj2 的 data 指针指向同一块内存
    // 当 obj1 和 obj2 析构时,会导致重复释放内存
    return 0;
}

2. 深拷贝(Deep Copy)

  • 定义:深拷贝不仅复制对象的成员变量的值,还会复制指针所指向的内容。即创建一个新的内存块,并将原对象指针指向的内容复制到新内存块中。
  • 优点
    • 每个对象拥有独立的资源,互不影响。
    • 避免了悬空指针和重复释放内存的问题。

示例:

class DeepCopy {
private:
    int* data;

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

    // 深拷贝的拷贝构造函数
    DeepCopy(const DeepCopy& other) {
        data = new int(*other.data); // 复制指针指向的内容
    }

    ~DeepCopy() {
        delete data;
    }

    void print() const {
        std::cout << "Value: " << *data << std::endl;
    }
};

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

    obj1.print(); // 输出: Value: 10
    obj2.print(); // 输出: Value: 10

    // obj1 和 obj2 的 data 指针指向不同的内存块
    // 析构时不会重复释放内存
    return 0;
}

3. 标准的拷贝构造函数

拷贝构造函数用于用一个对象初始化另一个对象。其标准形式如下:

ClassName(const ClassName& other);

实现深拷贝的拷贝构造函数:

class MyClass {
private:
    int* data;

public:
    // 构造函数
    MyClass(int value) {
        data = new int(value);
    }

    // 深拷贝的拷贝构造函数
    MyClass(const MyClass& other) {
        data = new int(*other.data); // 复制指针指向的内容
    }

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

    // 赋值运算符重载(深拷贝)
    MyClass& operator=(const MyClass& other) {
        if (this == &other) {
            return *this; // 处理自我赋值
        }
        *data = *other.data; // 复制指针指向的内容
        return *this;
    }

    void print() const {
        std::cout << "Value: " << *data << std::endl;
    }
};

4. 深拷贝与浅拷贝的选择

  • 浅拷贝适用于没有动态分配资源的对象(如基本数据类型、栈上的对象)。
  • 深拷贝适用于有动态分配资源的对象(如指针、堆上的对象)。

5. 总结

  • 浅拷贝:只复制成员变量的值,包括指针的值(地址),不复制指针指向的内容。
  • 深拷贝:复制成员变量的值,并为指针指向的内容创建新的内存块。
  • 拷贝构造函数:用于实现深拷贝,确保每个对象拥有独立的资源。
  • 赋值运算符重载:也需要实现深拷贝,避免资源泄漏和重复释放。

通过正确实现深拷贝,可以避免资源管理问题,确保程序的健壮性。

THE END
点赞12 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容