深拷贝和浅拷贝的核心区别在于是否为指针成员重新分配堆内存:浅拷贝仅逐值复制,导致多个对象共享同一堆内存而引发悬垂指针和重复释放;深拷贝则在拷贝构造函数中为指针成员new新内存并复制内容,确保资源独立,且凡管理动态资源的类必须遵循三/五法则自定义拷贝构造与赋值运算符。

深拷贝和浅拷贝是C++对象复制行为的核心概念,关键区别在于是否为指针成员重新分配堆内存。
浅拷贝:默认行为,只复制值,不复制资源
编译器自动生成的默认拷贝构造函数执行的是浅拷贝——对每个成员做逐个赋值。基本类型(int、double等)没问题;但若类中含指针成员(尤其指向new分配的内存),两个对象的指针会指向同一块堆区。一旦其中一个对象析构并释放该内存,另一个对象的指针就变成悬垂指针,后续访问或再次析构将引发未定义行为(如崩溃、重复释放)。
- 触发场景:用一个已存在对象初始化新对象(MyClass obj2 = obj1;)、函数传值、容器插入含指针成员的对象
- 典型风险:两次调用析构函数释放同一块堆内存
深拷贝:手动控制,确保资源独立
深拷贝要求在拷贝构造函数(及拷贝赋值运算符)中,为指针成员在堆上重新new一块空间,并把原对象的数据内容复制过去。这样两个对象拥有各自独立的内存,互不影响。
- 必须自定义:只要类中管理了动态资源(如指针 + 对应的delete析构逻辑)
- 配套原则:“三法则”或“五法则”:有自定义析构函数/拷贝构造/拷贝赋值,通常需一并实现其余几个,避免资源管理错乱
何时必须自定义拷贝构造函数?
不是“想不想”,而是“不得不”——只要类满足以下任一条件,就必须显式定义拷贝构造函数(并大概率要配拷贝赋值运算符):
立即学习“C++免费学习笔记(深入)”;
- 含有指向堆内存的裸指针,且析构函数中用delete释放它
- 持有系统资源(如文件句柄、socket描述符),需在拷贝时申请新资源而非共享
- 使用了std::unique_ptr等移动语义专属智能指针(此时默认拷贝被禁用,编译报错)
面试常考提醒
面试官往往不只问定义,更关注你能否识别问题场景并给出正确解法:
- 看到类里有char* name;和~Person() { delete[] name; },立刻意识到必须写深拷贝
- 能手写出带异常安全的深拷贝构造:先new再复制,失败则抛异常,避免内存泄漏
- 知道现代C++推荐用std::string、std::vector替代裸指针,它们内部已实现深拷贝,可规避大部分手动管理需求










