含有指针的对象,在相互拷贝时(浅拷贝:简单的赋值),会在析构函数重复释放相同地址的堆区空间而产生错误。
例如以下程序:
#include "bits/stdc++.h"
using namespace std;
class demo
{
public:
demo() {}
//有参构造函数
demo(const int age=0)
{
m_age = new int(age);
}
//析构函数
~demo()
{
cout << "m_age指向的地址是:" << m_age << endl;
if (m_age != nullptr)
{
delete m_age;
m_age = nullptr;
}
}
private:
int *m_age;
};
int main(int argc, char **argv)
{
demo d1(22);
demo d2(d1);
return 0;
}
运行结果如下:
m_age指向的地址是:0x55db53c67e70 m_age指向的地址是:0x55db53c67e70 free(): double free detected in tcache 2 已放弃 (核心已转储)
可见使用默认拷贝构造时,简单的值拷贝会使得指针m_age指向同一个堆区内存,重复释放必然会错误。
重载等号运算符号的方式解决 demo &operator=(const demo &obj)
{
//先释放旧有内存
if (this->m_age != nullptr)
{
delete m_age;
m_age = nullptr;
}
//再创建新内存
m_age = new int(*obj.m_age);
return *this;
}
重写拷贝构造函数的方式解决
demo(const demo &obj)
{
m_age = new int(*obj.m_age);
}
上述两种方式采用深拷贝,在堆区重新申请空间,进行拷贝操作,释放时释放各自申请的堆区内存,避免了重复释放



