浅拷贝只复制指针值导致共享内存,深拷贝则分配新内存并复制数据;需手动实现拷贝构造与赋值运算符,或用std::string等现代工具自动管理。

深拷贝和浅拷贝的区别核心在于:浅拷贝只复制对象的值(包括指针变量本身的地址),而深拷贝会为指针所指向的堆内存重新分配空间并复制内容。
浅拷贝:只复制指针,不复制数据
默认的拷贝构造函数和赋值运算符执行的就是浅拷贝。如果类中包含指针成员,多个对象会共享同一块堆内存,容易导致重复释放、野指针或数据被意外修改。
例如:
class BadString {
public:
char* data;
BadString(const char* s) {
data = new char[strlen(s) + 1];
strcpy(data, s);
}
// 没有自定义拷贝构造函数 → 编译器生成浅拷贝版本
~BadString() { delete[] data; }
};
int main() {
BadString s1("hello");
BadString s2 = s1; // 浅拷贝:s2.data 和 s1.data 指向同一块内存
// s1 和 s2 析构时都会 delete[] data → 二次释放,未定义行为!
}
深拷贝:复制数据本身,各自独立
需要手动实现拷贝构造函数和赋值运算符(遵循“三法则”或C++11后的“五法则”),在堆上为新对象分配新内存,并把原对象的数据完整复制过去。
立即学习“C++免费学习笔记(深入)”;
正确写法示例:
class GoodString {
char* data;
public:
GoodString(const char* s = "") {
data = new char[strlen(s) + 1];
strcpy(data, s);
}
// 深拷贝构造函数
GoodString(const GoodString& other) {
data = new char[strlen(other.data) + 1];
strcpy(data, other.data);
}
// 深拷贝赋值运算符(注意自我赋值检查)
GoodString& operator=(const GoodString& other) {
if (this == &other) return *this; // 自我赋值保护
delete[] data; // 释放原有资源
data = new char[strlen(other.data) + 1];
strcpy(data, other.data);
return *this;
}
~GoodString() { delete[] data; }};
现代C++推荐:用智能指针或标准容器避免手动管理
手动写深拷贝容易出错。更安全的做法是让类不直接持有裸指针:
- 用 std::string 替代 char* → 自动深拷贝,无需手写
- 用 std::vector
替代 T* + size → 内置深拷贝语义 - 用 std::unique_ptr
或 std::shared_ptr → 明确所有权,避免误删
例如:
class ModernString {
std::string data; // std::string 已经实现了正确的深拷贝
public:
ModernString(const char* s) : data(s) {}
// 无需写拷贝构造、赋值、析构 —— 默认行为就是安全的深拷贝
};
如何判断是否需要深拷贝?
关键看类中是否有指向动态分配内存的指针成员,且该指针的生命周期由当前对象管理(即对象负责 new/delete)。如果有,就必须深拷贝;否则默认拷贝即可。
简单口诀:谁 new,谁 copy;谁 delete,谁 clean。








