在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内存。
总结
- 浅拷贝:默认拷贝构造函数和赋值操作符进行逐成员的浅拷贝,可能导致多个对象共享同一块动态分配的内存,容易引起悬空指针等问题。
- 深拷贝:显式定义拷贝构造函数和赋值操作符,确保复制对象时也复制动态分配的内存或其他资源,从而创建完全独立的副本。
在实际应用中,需要根据具体情况选择使用浅拷贝或深拷贝。如果对象包含指向动态分配内存的指针,一般建议使用深拷贝以避免内存管理问题。