浅拷贝指的是简单地将一个对象的值复制给另一个对象,包括对象的所有成员变量,这意味着两个对象将共存相同的内存地址,对其中一个对象的修改会影响到另一个对象。浅拷贝默认通过复制构造函数和赋值操作符完成。
相比之下,深拷贝会创建一个新的对象,并赋值对象中的所有成员变量,包括对动态分配内存的指针的复制,这样每个对象都有自己的独立内存空间,深拷贝需要自定义复制构造函数和赋值操作符重载。
例子:
#include <iostream>
using namespace std;
class Person{
public:
int* height;
Person(int value){
height = new int(value); //height中存的是堆区数据的地址
}
~Person(){
if(height!=NULL){
delete height;
height = NULL;
}
cout << "析构" << endl;
}
};
int main(){
Person p1(160);
Person p2(p1); //编译器默认给的拷贝构造函数,做的是浅拷贝操作,
//即height = p1.height,拿到的是同一个地址
//上述代码会出错,因为浅拷贝会导致堆区的内存重复释放
//栈先进后出,p2会先调用析构函数,那么height指针指向的堆中数据会被清除,
//但是p1也会调用一次,所以导致重复释放,故报错。
}
在上面代码注释提到的问题解决办法就是自定义拷贝构造函数,使用深拷贝来解决问题
class Person{
public:
int* height;
Person(value){
height = new int(value); //height中存的是堆区数据的地址
}
Person(const Person &p){ //const防止误更改
height = new int(*p.height); //重新申请一块堆内存,就不会出现重复释放的问题。
}
~Person(){
if(height!=NULL){
delete height;
height = NULL;
}
cout << "析构" << endl;
}
}
int main(){
Person p1(160);
Person p2(p1); //此时调用自己定义的拷贝构造函数,故不会报错
}