面试宝典上的vector析构函数

本文探讨了C++中vector容器在析构过程中的行为,包括内存管理和元素删除,对于理解和使用vector在面试中至关重要。
摘要由CSDN通过智能技术生成
面试宝典上的vector析构函数

#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;
}

书上说这段程序的错误是vector对象指针能够自动析构,所以不需要调用delete a1,
否则会造成两次析构。

总结一下
1. vector <CDemo> *a1 = new vector <CDemo>(); a1是new出来的,所以必须要手工delete.这是对a1本身而言,而与a1内存储的数据无关。
2. a1 -> push_back(d1); 这部操作比较复杂,因为你的vector是存储类,而不是类指针。所以首先会在栈上创建d1的一个拷贝d1_1,压入栈,作为参数传递给push_back。然后在push_back中,创建d1_1的拷贝d1_2,d1_2是存储在a1管理的内存中。然后push_back return,d1_1出栈,调用d1_1的析构。
3. delete a1; a1中存有d1_2,所以会删除d1_2,自然会调用d1_2的析构函数。
4. 在main中return 0, d1被自动删除,此时调用d1的析构函数。
5. 因为class CDemo没有拷贝构造函数,所以创建拷贝时只是简单的把新对象中每个成员变量的值设置成与原来的对象相等。相当于运行memcpy。这时问题就来了,因为你的一个成员是char *str; 这样d1,d1_1,d1_2的str都是指向同一个地址。所以只有第一次调用CDemo的析构函数时能运行正确,以后的都会出错。因为一个地址只能释放一次。
6. 如果你的vector改为vector <CDemo*> *a1 = new vector <CDemo*>(); 即存储类指针,那么在执行delete a1之前,还要手工去删除vector中的每个元素。
7. 如何验证:在析构函数中用cout输出字符串。

---------------------------------------------------------------------------------------------------

按我的理解:
代码执行到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)
{
cout < < "copy constructor:" < < i++ < < endl;
this->str = new char[strlen(cd.str)+1];
strcpy(str, cd.str);
}
函数在执行到a1 -> push_back(d1);
d1的副本会在堆栈中申请另外的内存,而不是直接指向d1.str所指向的内存。这个时候你再看代码的执行:
代码执行到delete a1的时候vector调用了对象的析构函数~CDemo(){if(str) delete [] str;} ,这个时候delete掉的是副本里申请的内存(深拷贝实现)。
当代码执行完毕需要析构CDemo d1的时候,delete掉的是d1.str = new char[32]; 没有重复delete,这样就行了。
所以delete a1是应该的,只是要在类里面加一个深拷贝的拷贝构造函数。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值