此文章是关于“堆区的内存被重复释放”的问题
#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() {
if (m_Height != NULL) {
delete m_Height;
m_Height = NULL;
}
cout << "Person的析构函数调用" << endl;
}
public:
int m_Age;
int* m_Height;
};
void test01() {
Person p1(18,160);
cout << "p1的年龄:" << p1.m_Age << "身高为:" << *p1.m_Height << endl;
Person p2(p1);
cout << "p2的年龄:" << p2.m_Age << "身高为:" << *p2.m_Height << endl;
}
int main() {
test01();
}
根据“浅拷贝”的概念——如果属性是基本类型,拷贝的就是基本类型的值;如果属性是内存地址(引用类型),拷贝的就是内存地址,我们得到如下图片所呈现的结果:
根据栈区先进后出的特点,析构函数先清理对象p2,再清理对象p1.
在完成p2的析构函数之后,p1,p2指向的空间已经被释放掉了,此时的p1为野指针,p2为空指针。
因为野指针不能判断是否为NULL来避免,所以在执行p1的析构函数时,同样也可以进入if语句。
但在执行p1析构函数中的delete m_Height时,相同的一片空间被再次释放,此时就会报错,即“堆的内存空间被重复释放".
解决方法:
在Person类中,定义一个拷贝函数
Person(const Person& p) {
cout << "Person拷贝构造函数调用" << endl;
m_Age = p.m_Age;
//m_Height=p.m_Height; 编译器默认实现就是这行代码
//深拷贝操作
m_Height = new int(*p.m_Height);
}
”深拷贝“操作——在堆区重新申请空间,进行拷贝操作。