关于“深拷贝”,下列说法正确的是:
深拷贝和浅拷贝都是指针或引用类型数据的复制方式。
浅拷贝,又称为地址拷贝,只是复制了指针或引用的地址,多个对象指向同一块内存空间,这样在一个对象中对这个内存空间进行改变时,其余的对象也会受到影响。例如,当我们定义一个类并使用浅拷贝时,如果两个类对象有指针成员,则它们将共享相同的地址,当其中一个对象释放了这段内存,另一个对象中的指针成员将指向已释放的内存,从而导致错误。因此,在包含指针或动态内存分配的类中,使用浅拷贝可能会导致不可预期的结果。
深拷贝,是指将指针或引用所指向的实际内容全部复制一份到新的内存地址中,多个对象之间的指针指向不同的内存地址,每个对象都有自己的一份数据拷贝,互相之间不会影响。例如,在包含指针或动态内存分配的类中,使用深拷贝可以确保每个对象都有自己的一份内存,互相之间不会发生冲突。
| 操作 | 浅拷贝 | 深拷贝 |
|---|---|---|
| 栈数据复制(int stackData) | ✅ 复制值(如 stackData) | ✅ 复制值(如 stackData) |
| 指针地址处理(int* heapData) | ✅ 复制地址(共享堆内存) | ✅ 复制地址值,但指向新堆内存 |
| 动态资源内容复制(string str) | ❌ 不复制(仅共享) | ✅ 重新分配并复制内容 |
class MyClass {
private:
int stackData; // 栈数据(静态分配)
int* heapData; // 堆数据指针(动态分配)指针变量本身在栈上,指向的内存在堆上
std::string str; // 标准库类(内部管理动态资源)
public:
// 构造函数
MyClass(int stack, int size) : stackData(stack), heapData(new int[size]) {
for (int i = 0; i < size; ++i) {
heapData[i] = i;
}
}
// 析构函数
~MyClass() {
delete[] heapData;
}
// 浅拷贝构造函数(编译器默认生成的行为)
MyClass(const MyClass& other)
: stackData(other.stackData), heapData(other.heapData), str(other.str) {}
// 深拷贝构造函数
MyClass(const MyClass& other)
: stackData(other.stackData), str(other.str) {
// 重新分配堆内存并复制内容
heapData = new int[10];
for (int i = 0; i < 10; ++i) {
heapData[i] = other.heapData[i];
}
}
};
int main(){
MyClass a(10, 10); // a.stackData=10, a.heapData指向堆内存
MyClass b = a; // 执行浅拷贝(调用默认拷贝构造函数)
}