题目在书P105页
#include <iostream>
#include <cstdlib>
#include <vector>
using namespace std;
class CDemo{
public:
CDemo():str(NULL){};
~CDemo(){
if(str) delete[]str;
};
char* str;
}
};
int main(int argc,char** argv){
CDemo dl;
dl.str=new char[32];
strcpy(dl,str,"xxx");
vector<CDemo>*a1=new vector<CDemo>();
a1->push_back(dl);//容器在插入元素时,都会调用拷贝构造函数,当vector走出生存期时,会自动调用vector中所包含的每个元素的析构函数
//push_back时,内部会调用insert()函数,调用拷贝构造函数,创建dl的拷贝dl_1,存储在a1管理的内存中,和dl.str指向同一个地址
delete a1;//调用dl_1的析构函数,删除str,不会出错
return 0;//调用dl的析构函数,也删除str,就会出错。
}
上面这个问题就是浅拷贝的问题
CDemo中没有具体的拷贝构造函数时,会调用默认的拷贝构造函数,就是浅拷贝。
可以通过深拷贝解决这个问题,在CDemo中加入自己定义的拷贝构造函数
CDemo(const CDemo &cd)
{
cout < < "copy constructor:" < < i++ < < endl;
this->str = new char[strlen(cd.str)+1];
strcpy(str, cd.str);
}
函数在执行到a1 -> push_back(d1);
调用自己的拷贝构造函数创建的dl_1,会在堆栈中申请另外的内存,而不是直接指向d1.str所指向的内存地址。
当代码执行到delete a1的时候,vector调用了对象的析构函数~CDemo(),delete掉的是dl_1申请的内存(深拷贝实现)。
当代码执行完,需要析构 d1 的时候,delete掉的是d1.str = new char[32]; 没有重复delete。
所以,深拷贝就是开辟一块新的内存,防止重复delete
参考:面试宝典上的vector二次析构问题
还有一些vector容量限制时,插入元素时拷贝构造函数调用的例子,如下文:
STL容器与拷贝构造函数