浅拷贝:简单的赋值拷贝操作
深拷贝:在堆栈区重新申请空间,进行拷贝操作
浅拷贝从定义上我们可以看出,这只是一个简单的赋值操作,也就是将堆区已经申请空间内的数值进行一个赋值,无需重新申请空间。具体样例如下:
class person_a
{
public:
person_a()
{
cout << "这是一个默认构造函数" << endl;
}
person_a(int age)
{
m_age = age;
cout << "年龄是" << age << endl;
}
~person_a()
{
cout << "这是一个析构函数" << endl;
}
int m_age;
};
void test1()
{
person_a p1(18);
person_a p2(p1);
cout << "p1的年龄为" << p1.m_age << endl;
cout << "p2的年龄为" << p2.m_age << endl;
}
通过简单的括号赋值法将数值赋值给已经在栈区空间内的变量。
class person_a
{
public:
person_a()
{
cout << "这是一个默认构造函数" << endl;
}
person_a(int age, int weight)
{
//将数据创建到堆区
m_weight = new int(weight);
}
~person_a()
{
//将堆区开辟的数据做释放的操作
if (m_weight != NULL)
{
delete m_weight;
m_weight = NULL;
}
cout << "这是一个析构函数" << endl;
}
int *m_weight;
};
void test1()
{
person_a p1(120);
person_a p2(p1);
cout << "身高为:"<< *p1.m_weight << endl;
cout << "身高为:" << *p2.m_weight << endl;
}
当我们运行如上代码时,此时程序会报错:
对于以上的报错说明如下:
当使用new在堆区开辟一个内存空间时,是需要进行人为清除的,也就是通过析构函数中的内容。当我们通过浅拷贝来将对象p1中的内容拷贝到P2中时,也就将开辟堆区内存空间的地址复制到了p2中。按照内存操作先进后出的原则,当调用P2中的析构函数时,会将堆区新开辟的内存空间清理掉,而执行p1中的析构函数时,由于堆区内的空间已经被清理,则会报出如上的错误。
所以浅拷贝的弊端就是重复的释放堆区内存。
这种情况要怎么解决呢?
我们在复制一段数据的时候,我们可以在堆区内重新开辟一块内存开保存这块数据。这种方法我们称之为深拷贝。
深拷贝我们需要自己构造一个构造函数,其方法如下:
//使用指针常量的方法,将数值固定,使指针可以指向指定位置
person_a(const person_a &p)
{
cout << "拷贝构造函数调用" << endl;
//编译器默认实现的是如下代码
//m_weight = p.m_weight;
//深拷贝的操作是:通过new在堆区内开辟一段新的内存空间,并且将数值存放于这一新的内存空间内。
m_weight = new int(*p.m_weight);
}