深拷贝复制指针指向的内容并分配新内存,浅拷贝仅复制指针值。当类含指针成员时,默认拷贝为浅拷贝,会导致析构时重复释放内存,因此需自定义拷贝构造函数与赋值操作符实现深拷贝,或使用智能指针与标准库容器避免手动管理资源。

在c++中,深拷贝和浅拷贝是对象复制过程中两种不同的内存处理方式,它们的区别主要体现在对动态分配资源的处理上。当类中包含指针成员并使用默认的拷贝构造函数或赋值操作符时,容易引发问题,理解这两者的差异对于编写安全、稳定的代码至关重要。
什么是浅拷贝
浅拷贝是指在对象复制时,只复制成员变量的值,对于指针类型成员,仅复制其地址,而不复制其所指向的堆内存。这意味着原对象和副本中的指针会指向同一块动态分配的内存。
这种复制方式由编译器自动生成的拷贝构造函数和赋值操作符默认执行。如果类中没有显式定义这些函数,就会采用浅拷贝。
风险提示:当两个对象共享同一块堆内存,析构时可能导致重复释放(double free),从而引发程序崩溃。
例如:
立即学习“C++免费学习笔记(深入)”;
class String {
char* data;
public:
String(const char* str) {
data = new char[strlen(str)+1];
strcpy(data, str);
}
// 编译器生成默认拷贝构造函数 → 浅拷贝
~String() { delete[] data; }
};
若执行 String s2 = s1;,s1 和 s2 的 data 指针将指向同一块内存。当 s2 和 s1 析构时,delete[] 被调用两次,造成未定义行为。
什么是深拷贝
深拷贝是在复制对象时,不仅复制成员变量的值,还为指针成员重新分配一块新的内存,并将原对象所指向的数据内容复制到新内存中。这样,原对象和副本各自拥有独立的资源。
实现深拷贝需要手动定义拷贝构造函数和重载赋值操作符。
继续上面的例子,添加深拷贝支持:
String(const String& other) {
data = new char[strlen(other.data) + 1];
strcpy(data, other.data);
}
String& operator=(const String& other) {
if (this != &other) {
delete[] data; // 释放原有资源
data = new char[strlen(other.data) + 1];
strcpy(data, other.data);
}
return *this;
}
此时,每个对象都有自己的 data 内存空间,互不影响,避免了资源冲突。
何时需要深拷贝
当类中管理了动态资源(如堆内存、文件句柄、网络连接等)时,必须实现深拷贝,否则默认的浅拷贝会导致:
遵循“三法则”:如果需要析构函数、拷贝构造函数、赋值操作符中的任意一个,通常三个都需要自定义。
总结与建议
浅拷贝复制的是指针值,不复制指针指向的内容;深拷贝则复制内容并申请新内存。默认行为是浅拷贝,对于含指针成员的类,应主动实现深拷贝逻辑。
现代C++推荐使用智能指针(如 shared_ptr)或标准库容器(如 string、vector)来自动管理资源,减少手动内存操作,从根本上规避这类问题。
基本上就这些。掌握深浅拷贝的本质,才能写出更安全的C++类设计。