深拷贝、浅拷贝、移动语义
C++ 中的拷贝方式
1. 深拷贝(Deep Copy)
定义
深拷贝会复制对象的全部内容,包括对象中动态分配的资源。新对象与原对象完全独立,任何对新对象的修改都不会影响原对象。
实现
通常通过显式的拷贝构造函数或拷贝赋值运算符,手动分配新内存并复制资源。
示例
#include <iostream>
#include <cstring>
class MyClass {
char* data;
public:
MyClass(const char* str) {
data = new char[strlen(str) + 1];
strcpy(data, str);
}
// 深拷贝构造函数
MyClass(const MyClass& other) {
data = new char[strlen(other.data) + 1];
strcpy(data, other.data);
}
~MyClass() {
delete[] data;
}
void print() const {
std::cout << data << "\n";
}
};
int main() {
MyClass obj1("Hello");
MyClass obj2 = obj1; // 调用深拷贝构造函数
obj2.print(); // 输出: Hello
return 0;
}
特点
1.深拷贝是安全的,原对象和新对象的资源完全独立。
2.对象中有动态资源时需要手动实现深拷贝。
3.较耗费性能(特别是资源较大时)。
2. 浅拷贝(Shallow Copy)
定义
浅拷贝只复制对象中的指针或引用,而不复制它们所指向的实际资源。新对象和原对象共享同一块资源。
问题
如果不小心释放了共享的资源,会导致其他对象指向无效的内存,产生 悬挂指针(Dangling Pointer)。
示例
#include <iostream>
#include <cstring>
class MyClass {
char* data;
public:
MyClass(const char* str) {
data = new char[strlen(str) + 1];
strcpy(data, str);
}
// 默认浅拷贝(未自定义拷贝构造函数时)
MyClass(const MyClass& other) = default;
~MyClass() {
delete[] data;
}
void print() const {
std::cout << data << "\n";
}
};
int main() {
MyClass obj1("Hello");
MyClass obj2 = obj1; // 浅拷贝,指向同一资源
obj1.print(); // 输出: Hello
obj2.print(); // 输出: Hello
return 0;
}
特点
1.浅拷贝速度快,因为它仅复制指针的地址。
2.容易产生悬挂指针或资源泄漏问题。
3. 移动语义(Move Semantics)
定义
移动语义会将资源从一个对象“转移”到另一个对象,而不会创建或复制新的资源。原对象的资源被“搬走”,进入“有效但未定义状态”。
实现
使用移动构造函数和移动赋值运算符。
示例
#include <iostream>
#include <utility> // for std::move
class MyClass {
char* data;
public:
MyClass(const char* str) {
data = new char[strlen(str) + 1];
strcpy(data, str);
}
// 移动构造函数
MyClass(MyClass&& other) noexcept : data(other.data) {
other.data = nullptr; // 释放原对象的所有权
}
~MyClass() {
delete[] data;
}
void print() const {
std::cout << (data ? data : "Empty") << "\n";
}
};
int main() {
MyClass obj1("Hello");
MyClass obj2 = std::move(obj1); // 调用移动构造函数
obj2.print(); // 输出: Hello
obj1.print(); // 输出: Empty
return 0;
}
特点
1.移动语义速度快,不需要深拷贝。
2.常用于临时对象或需要高效转移资源的场景。
3.需要实现移动构造函数和移动赋值运算符。
4. 对比总结
拷贝方式 | 深拷贝 | 浅拷贝 | 移动语义 |
---|---|---|---|
实现复杂度 | 较高,需要手动复制资源 | 简单,默认行为 | 需要手动实现移动构造和赋值 |
效率 | 慢,涉及内存分配和复制 | 快,只复制指针 | 非常快,只转移资源所有权 |
资源独立性 | 独立的资源副本 | 共享资源 | 资源被转移,独占 |
适用场景 | 资源独立且需频繁复制 | 快速拷贝,无需独立资源 | 资源需要转移时,高效操作 |
5.总结
- 深拷贝:适用于需要独立资源的场景,比如资源管理类(文件、内存等)。
- 浅拷贝:简单但容易导致问题,仅适用于无需独立资源的情况。
- 移动语义:是现代 C++ 的高效资源管理方式,适合转移资源的场景。