拷贝构造与赋值本质不同:前者初始化新对象,后者为已存在对象赋值;深拷贝需独立复制堆内存以避免资源共享,浅拷贝仅复制指针值;现代C++应优先用RAII智能指针和容器替代裸指针。
拷贝构造和赋值在 C++ 中本质都是对象复制,但触发时机、语义责任和实现细节完全不同;深拷贝与浅拷贝的区别,核心在于是否对指针所指向的堆内存做独立副本 —— 这直接决定多个对象是否共享同一块动态资源,是资源管理正确性的分水岭。
当定义新对象并用同类型对象初始化时调用,例如:T a; T b = a; 或 func(a)(传值)、return a;(返回局部对象)。编译器默认生成的拷贝构造函数执行的是逐成员位拷贝(shallow copy)。
若类中含裸
指针(如 int* p;),默认拷贝会让两个对象的 p 指向同一块堆内存 —— 后续析构时重复 delete 就会崩溃。
必须手动定义拷贝构造函数来实现深拷贝:
new)使用 = 对已构造对象赋值时调用,例如:a = b;。默认赋值运算符同样只做浅拷贝,且不处理自我赋值(a = a;)和原有资源释放问题。
手写赋值运算符需满足“三法则”(Rule of Three):只要写了拷贝构造、析构或赋值之一,通常三个都得自己写。典型实现模式:
if (this == &rhs) return *this;)delete[] p;)*this 支持链式赋值(a = b = c;)浅拷贝只是复制指针值,多个对象共用同一份堆内存 —— 简单但危险;深拷贝为每个对象创建独立副本 —— 安全但开销大、需手动管理。
判断是否需要深拷贝,看类是否拥有「独占性资源」:
char* 数组)、非 RAII 封装的句柄std::shared_ptr 自带引用计数)、std::string、std::vector 等标准容器(它们内部已实现深拷贝或写时复制)const 和明确文档说明)真正解决深浅拷贝难题的根本方法,不是写更复杂的拷贝函数,而是从设计上消除裸指针:
std::vector 替代 int* + size_t size
std::string 替代 char* + 手动 strcpy
std::unique_ptr 表达独占所有权(移动语义自动禁用拷贝)std::shared_ptr 表达共享所有权(拷贝即增加引用计数)这样,默认生成的拷贝/赋值函数就天然安全,既无内存泄漏也无重复释放 —— 深浅拷贝之争自然消解。