C++中的深拷贝和浅拷贝有什么区别?(代码示例)

12次阅读

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

C++中的深拷贝和浅拷贝有什么区别?(代码示例)

深拷贝和浅拷贝的区别核心在于:浅拷贝只复制对象的值(包括指针变量本身的地址),而深拷贝会为指针所指向的内存重新分配空间并复制内容。

浅拷贝:只复制指针,不复制数据

默认的拷贝构造函数和赋值运算符执行的就是浅拷贝。如果类中包含指针成员,多个对象会共享同一块堆内存,容易导致重复释放、野指针或数据被意外修改。

例如:

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_ptrstd::shared_ptr → 明确所有权,避免误删

例如:

class ModernString {     std::string data; // std::string 已经实现了正确的深拷贝 public:     ModernString(const char* s) : data(s) {}     // 无需写拷贝构造、赋值、析构 —— 默认行为就是安全的深拷贝 };

如何判断是否需要深拷贝?

关键看类中是否有指向动态分配内存的指针成员,且该指针的生命周期由当前对象管理(即对象负责 new/delete)。如果有,就必须深拷贝;否则默认拷贝即可。

简单口诀:谁 new,谁 copy;谁 delete,谁 clean。

text=ZqhQzanResources