深拷贝函数需协同析构、赋值与移动语义:裸指针须new+复制内容并防double free;const char*等只读指针不深拷贝;std::string等标准类型用默认行为;推荐copy-and-swap赋值与noexcept swap,并遵循五法则确保资源安全。

设计一个既安全又高效的深拷贝函数,核心在于明确“谁该被深拷贝”、严格管理资源生命周期,并避免冗余操作。它不是写个 new + memcpy 就完事,而是要和析构、赋值、移动等语义协同一致。
先判断:哪些成员真需要深拷贝?
不是所有指针都要深拷贝——关键看所有权。
- 裸指针(
int*,char*)指向堆内存且由当前对象独占管理 → 必须深拷贝 -
const char*仅作只读观察,内存由外部分配 → 不该深拷贝,复制指针值即可 -
std::string、std::vector、std::shared_ptr等标准类型 → 内部已实现深拷贝语义,直接用默认行为 -
std::unique_ptr→ 不可拷贝,若需“深拷贝效果”,必须在拷贝构造中调用std::make_unique并逐字段复制
拷贝构造函数:专注初始化,不碰旧资源
构造函数里 this 还没完全成型,只负责从 other 安全读取并分配新内存。
- 在初始化列表中设置非指针成员(如
size_、capacity_) - 指针成员不在初始化列表中赋值,留到函数体里用
new或std::make_unique分配 - 用
std::copy或strcpy复制内容,绝不能写data_ = other.data_ - 若分配失败(
new抛异常),确保对象处于有效但未完成构造的状态(基本异常安全)
赋值运算符:必须防自赋值,优先用 copy-and-swap
赋值是运行时行为,this 已存在,可能持有资源,逻辑比构造更复杂。
- 传统写法需三步:检查自赋值 → 释放旧资源 → 分配+复制新资源
- 但容易出错:比如
delete[]后new失败,对象就残缺了 - 推荐 copy-and-swap:参数按值传入(触发拷贝构造),再交换成员,靠临时对象析构自动清理旧资源
- swap 函数应标记为
noexcept,确保 STL 容器能安全调用
配套必须写全:析构 + 移动 + 五法则闭环
深拷贝不是孤立操作,它和整个资源管理环环相扣。
- 析构函数必须释放所有
new出来的内存,且每个指针判空或初始化为nullptr - 写了拷贝构造和赋值,编译器就不会自动生成移动构造/移动赋值 → 若类用于容器(如
std::vector),必须显式定义或= default,否则退化为低效拷贝 - 移动操作中,源对象指针必须置为
nullptr,防止双重析构 - 用
g++ -Wextra或clang++ -Weffc++编译,可捕获“有指针但无拷贝构造”的隐患

















