在C++中,浅拷贝(Shallow Copy)和深拷贝(Deep Copy)是两种不同的对象拷贝方式。它们之间的主要区别在于对指针成员的处理方式:
浅拷贝(Shallow Copy)
- 浅拷贝在C++中通常是指默认的拷贝构造函数和赋值操作符。
- 浅拷贝只复制对象中的基本数据类型的值,而不复制指向动态分配内存(如堆上分配的内存)的指针所指向的内容。换句话说,浅拷贝只复制指针的值(即内存地址),而不复制指针所指向的实际数据。
#include <iostream>
#include <cstring>class Shallow {
public:char* data;Shallow(const char* value) {data = new char[strlen(value) + 1];strcpy(data, value);}// 默认的拷贝构造函数Shallow(const Shallow& other) = default;~Shallow() {delete[] data;}void print() {std::cout << "Data: " << data << std::endl;}
};int main() {Shallow original("Hello");Shallow copy = original; // 使用默认拷贝构造函数进行浅拷贝copy.data[0] = 'h'; // 修改拷贝对象的数据original.print(); // 输出: "Data: hello",原始对象受到影响copy.print(); // 输出: "Data: hello"return 0;
}
在上述例子中,Shallow类的默认拷贝构造函数执行浅拷贝,使得copy对象和original对象共享同一个data指针。因此,修改copy对象的数据也会影响到original对象的数据。
深拷贝(Deep Copy)
- 深拷贝需要显式地定义拷贝构造函数和赋值操作符,以确保在复制对象时也复制所有动态分配的内存或其他资源。
- 深拷贝不仅复制对象中的基本数据类型的值,还复制指向动态分配内存的指针所指向的实际数据。也就是说,深拷贝为指针成员分配新的内存并复制内容,从而使新旧对象相互独立。
#include <iostream>
#include <cstring>class Deep {
public:char* data;Deep(const char* value) {data = new char[strlen(value) + 1];strcpy(data, value);}// 深拷贝构造函数Deep(const Deep& other) {data = new char[strlen(other.data) + 1];strcpy(data, other.data);}// 深拷贝赋值操作符Deep& operator=(const Deep& other) {if (this != &other) {delete[] data; // 释放已有资源data = new char[strlen(other.data) + 1];strcpy(data, other.data);}return *this;}~Deep() {delete[] data;}void print() {std::cout << "Data: " << data << std::endl;}
};int main() {Deep original("Hello");Deep copy = original; // 使用深拷贝构造函数copy.data[0] = 'h'; // 修改拷贝对象的数据original.print(); // 输出: "Data: Hello",原始对象不受影响copy.print(); // 输出: "Data: hello"return 0;
}
在上述例子中,Deep类的深拷贝构造函数和赋值操作符创建了一个完全独立的副本。修改copy对象的数据不会影响original对象的数据,因为它们各自拥有独立的data内存。
总结
- 浅拷贝:默认拷贝构造函数和赋值操作符进行逐成员的浅拷贝,可能导致多个对象共享同一块动态分配的内存,容易引起悬空指针等问题。
- 深拷贝:显式定义拷贝构造函数和赋值操作符,确保复制对象时也复制动态分配的内存或其他资源,从而创建完全独立的副本。
在实际应用中,需要根据具体情况选择使用浅拷贝或深拷贝。如果对象包含指向动态分配内存的指针,一般建议使用深拷贝以避免内存管理问题。