值拷贝、浅拷贝和深拷贝
✅ 一、基本概念
1. 值拷贝(Value Copy)
-
含义:将一个变量的值完整复制到另一个变量中。
-
对象级别表现:调用的是拷贝构造函数(copy constructor)。
-
特点:对基本类型或不含动态资源的对象,值拷贝通常等价于“成员逐个赋值”。
2. 浅拷贝(Shallow Copy)
-
含义:复制对象的值,但不复制其内部资源(如指针指向的堆内存),只复制指针地址。
-
风险:多个对象共享同一资源,可能导致悬挂指针、重复释放、资源篡改等问题。
3. 深拷贝(Deep Copy)
-
含义:复制对象的所有值,并为动态分配的资源重新分配空间并复制其内容,确保每个对象有自己的资源。
-
特点:对象间完全独立,不会互相影响,内存安全。
✅ 二、值拷贝、浅拷贝、深拷贝的发生时机
拷贝类型 | 发生时机 |
---|---|
值拷贝 | 拷贝基本类型变量(如 int , double 等)或 STL 容器中的 POD 类型元素 |
浅拷贝 | 类没有自定义拷贝构造函数时,编译器自动生成的构造函数默认执行浅拷贝 |
深拷贝 | 类中包含动态资源时,程序员需显式实现深拷贝构造函数与拷贝赋值运算符 |
✅ 三、对比如下
特性 | 值拷贝 | 浅拷贝 | 深拷贝 |
---|---|---|---|
复制内容 | 值 | 值 + 指针地址 | 值 + 指针指向内容 |
动态资源分配 | 否 | 否 | 是 |
安全性 | 安全 | 易出错:多重释放、悬挂指针等 | 安全:每个对象资源独立 |
对象独立性 | 独立 | 共享资源 | 完全独立 |
性能开销 | 小 | 小 | 较大(但安全) |
示例对象 | int a = b; | MyClass(const MyClass&) 默认 | MyClass(const MyClass&) 自定义 |
✅ 四、实际代码示例
浅拷贝示例(默认拷贝)
class MyClass { public: int* data; MyClass(int val) { data = new int(val); } // 默认浅拷贝构造函数 ~MyClass() { delete data; } }; void test() { MyClass a(10); MyClass b = a; // 浅拷贝:data 指向同一块内存,b 和 a 冲突 }
深拷贝示例(手动构造)
class MyClass { public: int* data; MyClass(int val) { data = new int(val); } // 深拷贝构造函数 MyClass(const MyClass& other) { data = new int(*other.data); // 拷贝内容而非地址 } ~MyClass() { delete data; } };
✅ 五、应用场景总结
场景 | 建议使用方式 | 原因/说明 |
---|---|---|
基本数据类型拷贝 | 值拷贝即可 | 开销小,语义清晰 |
拷贝 STL 容器元素 | 默认拷贝或 move | STL 容器元素通常支持深拷贝(比如 std::string ) |
类中含动态分配资源 | 深拷贝 | 避免浅拷贝导致的内存错误 |
大对象不希望复制资源 | 移动语义(C++11+) | 如 std::vector , 可使用 std::move() 提高效率 |
遍历对象不希望拷贝 | const auto& 遍历 | 避免性能浪费,防止无意修改 |
只需只读访问且无资源冲突 | 浅拷贝或引用都可 | 看具体语义和类内部资源结构 |
✅ 总结一句话:
-
值拷贝适用于基本类型;
-
浅拷贝默认由编译器生成,容易出问题;
-
深拷贝需要自己实现,适用于资源敏感型对象;
-
引用和移动语义是现代 C++ 中更高效且安全的替代手段。