浅拷贝仅复制类成员的值,包括指针,但不复制指针指向的数据。深拷贝创建指针指向的数据的新副本,从而防止内存共享和双重释放。
示例:
class Buffer { public: Buffer(size_t size) : size(size), data(new int[size]) {} // 浅拷贝(错误) Buffer(const Buffer& other) : size(other.size), data(other.data) {} // 深拷贝(正确) Buffer& operator=(const Buffer& other) { if (this != &other) { delete[] data; size = other.size; data = new int[size]; std::copy(other.data, other.data + size, data); } return *this; } ~Buffer() { delete[] data; } private: size_t size; int* data; };
如果类包含指向动态数组的指针,为什么默认的拷贝构造函数和赋值运算符不足以使用?
正确答案:
默认的拷贝实现了浅拷贝。两个对象将指向同一个数组,并且在销毁时会尝试两次释放同一内存(双重释放),这会导致崩溃。
故事 在一个大型服务器应用程序中,已经实现了自己的Image类,管理像素的动态缓冲区。开发者没有实现深拷贝,导致在线程之间通过值传递Image对象时发生双重释放内存,导致每隔几天崩溃一次。
故事 在一个学生项目中,使用了一个名为Field的容器,里面包含指向动态分配的单元数组的指针。调整数组大小时,拷贝构造函数仅复制指针,导致两个容器操作同一内存区域,导致数据不一致和难以发现的错误。
故事 在一个旧的C++图形引擎代码中,实现的Texture类没有自己的析构函数和赋值运算符,导致在复制和赋值临时纹理对象时发生内存泄漏。