C++自定义vector存储动态对象指针时如何正确实现析构?
问题结论
你当前的通用模板vector绝对不能加遍历delete每个元素的析构逻辑,你的疑问要分场景处理:
仅执行
delete[] elem的话,不会自动调用你new出来的obj对象的析构函数,会出现内存泄漏。delete[] elem只会释放elem指向的数组本身占用的内存(也就是存储3个obj*指针的内存空间),不会对指针指向的堆上obj对象做任何处理,obj的析构逻辑自然也不会触发。你不能直接修改通用vector的析构函数加遍历delete逻辑,原因有两个:
- 你的vector是模板类,
T可以是任意类型,如果T不是指针类型(比如int、std::string、普通自定义类),delete elem[i]会直接编译报错,delete运算符只能作用于指针类型。 - 就算
T是指针类型,也不代表指针指向的内存都是用new分配的:可能是指向栈上的对象、可能是用new[]分配的、也可能是其他内存分配器返回的地址,你直接对所有元素执行delete会触发未定义行为,大概率导致程序崩溃。
解决方案
你可以根据自己的需求选以下实现方式:
- 如果要做通用vector容器,保持原来的
delete[] elem析构逻辑即可,存储裸指针时由使用者自己在容器销毁前遍历释放每个指针指向的资源,或者直接用智能指针代替裸指针:vector<std::unique_ptr<obj>>/vector<std::shared_ptr<obj>>,智能指针会在自身生命周期结束时自动释放指向的对象,不需要你修改vector的任何逻辑。 - 如果你要做一个专门用于存储
new出来的裸指针、且由容器接管指针所有权的特殊vector,单独写一个template <typename T> struct vector<T*>的偏特化版本,在偏特化版本的析构函数里执行遍历delete的逻辑即可,同时要明确告知使用者该容器的特性,禁止传入非new分配的指针。
内容的提问来源于stack exchange,提问作者YoRHa
相关产品推荐
相关产品推荐

