下面一段程序退出时会出现错误吗(摘自面试宝典)?
#include<iostream>
using namespace std;
class CDemo {
public:
CDemo() :str(nullptr) {};
~CDemo()
{
if (str) delete [] str;
};
char* str;
};
int main()
{
CDemo d1;
d1.str = new char[32];
vector<CDemo>* a1 = new vector<CDemo>();
a1->push_back(d1);
delete a1;
return 0;
}
退出时会出现重复 delete 同一片内存,程序崩溃。首先
vector<CDemo>* a1 = new vector<CDemo>(); 指定一个指针,指向 vector<CDemo>,并用 new 操作符进行了初始化,所以必须在适当的时候释放 a1 所占有的内存空间,因此调用 "delete a1" 这句是正确的。
但是为什么会释放同一片内存两次呢?
在执行 “a1->push_back(d1);” 这条语句时,会调用 CDemo 的拷贝构造函数,现在 CDemo 没有定义拷贝构造函数,但是编译器会为 CDemo 类自动构建一个默认的拷贝构造函数(浅拷贝)。
执行“a1->push_back(d1);”后,a1 里面的 CDemo 元素与 d1 里面的是不同的对象,但是 a1 里 CDemo 元素的 str 与 d1.str 指向的却是同一块内存。
而局部变量 CDemo d1 在 main 函数退出时,自动释放所占有的内存空间,此时会自动调用 CDemo 的析构函数,问题就出现在这里。前面 delete a1 已经把 d1.str 释放了,main 函数退出时,又要释放已经释放的 d1.str 内存空间,所以程序最后崩溃。
此题归根结底是浅拷贝与深拷贝的问题,如果 CDemo 类添加一个如下的拷贝构造函数就没有问题了:
CDemo(const CDemo& cd){
this->str = new char[strlen(cd.str) + 1];
strcpy(str, cd.str);
}