#include <vector>
using namespace std;
class CDemo{
public:
CDemo():str(NULL){}
~CDemo(){if(str) delete [] str;}
char *str;
};
int main()
{
CDemo d1;
d1.str = new char[32];
strcpy(d1.str, "trend micro");
vector <CDemo> *a1 = new vector <CDemo>();
a1 -> push_back(d1);
delete a1;
return 0;
}
上面的代码会两次调用CDemo的析构函数。在C++ Primer上说,不需要调用delete a1,否则容易造成两次析构。但是a1是new出来的,一般new出来的都必须要手动调用delete去释放内存。
所以这里有点不是很明白。后来看到网上有一种观点,觉得挺有道理的。是这样解释的。代码执行到delete a1时候,vector调用了对象的析构函数~CDemo(){if(str) delete [] str;},这时已经把d1.str = new char[32]给释放掉了,由于没有定义拷贝构造函数实现深拷贝,当代码执行完毕的时候,CDemo d1对象还会自己析构一次,又会调用~CDemo(){if(str) delete [] str;}一次,这个时候会出现重复delete,所以会出错。如果定义了拷贝构造函数实现深拷贝
CDemo(const CDemo &cd)
{
this->str = new char[strlen(cd.str)+1];
strcpy(str, cd.str);
}
函数在执行到a1->push_back(d1),d1的副本会在堆栈中申请另外的内存,而不是直接指向d1.str所指向的内存。这时代码执行到delete a1的时候vector调用了对象的析构函数~CDemo(),此时delete掉的是副本里申请的内存(深拷贝实现),当代码执行完毕时需要析构CDemo d1的时候,delete掉的是d1.str = new char[32],没有重复delete。
如果vector改为vector<CDemo *> *a1 = new vector<CDemo *>();即存储类指针,那么在执行delete a1之前,还要手工去删除vector中的每个元素。
转载于:https://blog.51cto.com/shaxquan/384569