1、浅层复制构造函数(利用默认的复制构造函数)
如果对象A的数据成员中有指针,那么当我们把对象A复制给对象B的时候,此时对象A和对象B中的指针数据成员都是指向同一块内存区域的,当两个对象中的任意一个对象被删除的时候,指针数据成员的那块内存区域也会被删除,因此另一个对象的成员指针变成了野指针,程序也会因此而崩溃。
class MyClass
{
public:
MyClass()
{
p = new int;
*p = 10;
}
~MyClass()
{
delete p;
p = NULL;
}
void set(int i)
{
*p = i;
}
int *getAdress()
{
return p;
}
private:
int *p;
};
int main()
{
//创建一个对象p
MyClass *p = new MyClass;
//调用默认的复制构造函数创建对象p1
MyClass p1(*p);
//两个对象指针数据成员的地址是一样的
cout<<"对象p的数据成员地址:"<<p->getAdress()<<endl;
cout<<"对象p1的数据成员地址:"<<p1.getAdress()<<endl;
//对象p改变了数据成员的值,p1成员的值也会被改变
p->set(999);
//删除对象p,同时p1的指针成员也被删除掉了,因为他们指向的是同一块内存地址
delete p;
//程序结束时崩溃
//因为程序结束时会自动释放p1,这时发现指针成员已经不存在了,做了一次重复的删除,所以程序崩溃
return 0;
}
2、深层复制构造函数(自定义复制构造函数)
解决上述问题,需要显式定义一个复制构造函数,在复制构造函数中为成员指针分配新的内存空间,然后将旧对象成员的数据赋值给新对象成员,两个对象的数据成员各自拥有不同的内存区域,因此不会相互影响,这种方式就叫做深层复制。
class MyClass
{
public:
MyClass()
{
p = new int;
*p = 10;
}
MyClass(const MyClass &m)
{
//申请一块新的内存存放指针对象
p = new int;
*p = *(m.p);
}
~MyClass()
{
delete p;
p = NULL;
}
void set(int i)
{
*p = i;
}
int *getAdress()
{
return p;
}
private:
int *p;
};
int main()
{
//创建一个对象p
MyClass *p = new MyClass;
//调用默认的复制构造函数创建对象p1
MyClass p1(*p);
//两个对象指针数据成员各自有用自己的内存区域
cout<<"对象p的数据成员地址:"<<p->getAdress()<<endl;
cout<<"对象p1的数据成员地址:"<<p1.getAdress()<<endl;
//对象p改变了数据成员的值,不会影响p1
p->set(999);
//删除p,不会影响p1
delete p;
return 0;
}