Shallow copy(浅复制)只复制对象字段的值,包括指针,但不复制动态分配的内存。结果,两个对象指向同一块内存。这可能会在数据更改或释放内存时导致错误。
Deep copy(深复制)创建对象所引用的所有资源的完整副本,以便每个对象都有自己的数据副本。
需要deep copy的情况:
深复制实现示例:
class ArrayHolder { public: ArrayHolder(size_t size) : sz(size), data(new int[size]) {} ~ArrayHolder() { delete[] data; } // 深复制构造函数 ArrayHolder(const ArrayHolder& other) : sz(other.sz), data(new int[other.sz]) { std::copy(other.data, other.data + other.sz, data); } // 深复制赋值操作符 ArrayHolder& operator=(const ArrayHolder& other) { if (this != &other) { delete[] data; sz = other.sz; data = new int[sz]; std::copy(other.data, other.data + sz, data); } return *this; } private: size_t sz; int* data; };
问题: 如果在复制构造函数中仅仅复制指针的值,它会正确工作吗?
回答: 不会,这会导致在两个对象销毁时发生双重删除内存。需要实现深复制以正确管理资源。
故事
在一个项目中,为了在模块之间传递数组,使用了类的对象,其中默认的复制构造函数只复制指针(浅复制)。结果,当临时对象超出作用域时,数组被销毁,而主对象则保留“悬挂”的指针,这导致了未定义的行为和应用程序崩溃。
故事
在一个处理图像的库中,反复复制了包含动态分配缓冲区的对象。由于缺乏深复制,在一个对象中释放内存后,另一个对象可以访问已释放的区域。这表现为数据损坏和对象删除时的崩溃。
故事
在将过时的代码与现代标准集成时,旧类中既未实现复制构造函数,也未实现赋值操作符。与标准库容器一起使用这些类会导致意外崩溃,因为容器会浅复制对象。