先说明他的应用:如果属性有在堆区开辟的,一定要自己提供拷贝构造函数,防止浅拷贝带来的问题
首先说明下深浅拷贝
浅拷贝:简单的赋值拷贝操作,执行的是编译软件自己带的默认拷贝
(会带来堆区的内存被重复释放的问题,导致程序崩掉,用深拷贝可以解决此类问题)
深拷贝:根据以下代码自行理解
#include<iostream>
using namespace std;
/*
深浅拷贝
浅拷贝:简单的赋值拷贝操作 ,带来的问题是堆区的内存重复释放(程序会报错,解决办法是运用深拷贝)
深拷贝:
*/
class person
{
public:
person()
{
cout << "person默认构造" << endl;
}
person(int age, int height)
{
m_age = age;
m_height = new int(height);
cout << "person有参构造" << endl;
}
//自己实现拷贝构造函数,解决浅拷贝带来的问题
person(const person& p)
{
cout << "person 拷贝构造函数调用" << endl;
m_age = p.m_age;
//m_height = p.m_height; 编译器默认实现的就是这行代码
//深拷贝操作
m_height = new int(*p.m_height);
}
~person()
{
//析构代码,将堆区开辟数据做释放操作
if (m_height != NULL)
{
delete m_height;
m_height = NULL;
}
cout << "person析构函数" << endl;
}
int m_age;
int* m_height;
};
void test01()
{
person p1(18,160);
cout << "p1的年龄为:" << p1.m_age <<"1的身高:"<< *p1.m_height << endl;
person p2(p1);
cout << "p2的年龄为:" << p2.m_age << "2的身高:" << *p2.m_height << endl;
}
int main()
{
test01();
return 0;
}
深拷贝就是自己重新定义拷贝构造函数,不用系统自带的构造函数。
在上面的代码中,在person类中定义了一个 *m_height属性,在 自己定义的有参构造时 用这个int型指针接收new开辟出来的处于堆区的那个地址,此时如果没有自己定义的那个析构函数(即若用编译器默认的构造函数)就会出现问题,让程序崩掉。
这个问题就是:用系统自带的拷贝构造时,在执行test01函数的 person p2(p1)这条命令时。实际上就是把p1这个空间完完全全连同地址完全复制了一次,尤其是在复制m_height这个属性时,p1和p2的 m_height属性的地址完全是同一个,这就会让你在调用析构函数中的命令时把同一个地址释放两次,这显然会导致程序出错!
而为了解决这个问题,深拷贝应运而生。
深拷贝的解决思路是:因为p1,p2的地址完全一样才会导致相同地址二次释放,可是如果给p2在堆区也开辟一片独立的属于自己的空间,释放时就各自释放各自的了。上述第32行代码就是做了这件事:他先把被拷贝的那个对象的m_height属性解引用出来,此时m_height的值就出来了,再给这个值在堆区new一片自己的空间,再用p2的对象(int型指针 m_height)来接收,这样,析构时p2就有的释放了,程序就不会报错了。