如何编写通用指针删除函数?现有实现是否合理?
你的通用指针删除函数的问题与优化方案
首先得说,你的代码虽然能编译运行,但存在两个关键隐藏问题,会埋下bug隐患:
问题1:函数内的obj = NULL;完全无效
你写的deletePointer函数接收的是void*的值拷贝——C++里参数默认是值传递,所以函数里修改的只是传入指针的副本,外面的原始指针根本不会被置为NULL。举个例子,你调用deletePointer(obj);之后,外面的obj还是指向已经被释放的内存地址,变成了野指针,后续如果不小心再访问它,会导致程序崩溃、数据损坏这类未定义行为。
问题2:delete void*会跳过析构函数,导致内存泄漏
当你把wstring*、vector*这类带有非平凡析构函数的指针转成void*再delete时,编译器无法识别对象的实际类型,也就不会调用对应的析构函数。比如wstring内部的字符缓冲区、vector的动态数组都不会被正确释放,这会造成内存泄漏,而且这种泄漏通常很难排查。
修正后的通用实现:用模板函数
要解决这两个问题,最直接的方法是写一个模板函数,既保留对象的类型信息,又通过引用传递修改原始指针:
#include <windows.h> #include <vector> #include <map> #include <string> #include <memory> using namespace std; struct testStruct { int nVal; _TCHAR tcVal[256]; testStruct() { wmemset(tcVal, 0, _countof(tcVal)); } }; template<typename T> void deletePointer(T*& obj) { if (obj) { delete obj; obj = nullptr; // 优先用nullptr(C++11+),比NULL更安全,避免类型歧义 } } int _tmain(int argc, _TCHAR* argv[]) { testStruct *obj = new testStruct; wstring *strVal = new wstring(); vector<wstring> *vecVal = new vector<wstring>; map<wstring,wstring> *mapVal = new map<wstring, wstring>; // 业务逻辑 deletePointer(obj); deletePointer(strVal); deletePointer(vecVal); deletePointer(mapVal); // 现在所有原始指针都被置为nullptr,不会变成野指针 return 0; }
模板函数会自动推导传入指针的类型,确保delete时调用正确的析构函数,同时通过引用传递T*&,修改的就是原始指针本身,置空操作能真正生效。
更优方案:彻底抛弃手动内存管理——用智能指针
其实在现代C++里,手动管理原始指针已经是不推荐的做法了,智能指针能帮你自动处理内存释放,从根源上避免野指针、内存泄漏这类问题。比如用std::unique_ptr(独占所有权)或者std::shared_ptr(共享所有权):
int _tmain(int argc, _TCHAR* argv[]) { // 用make_unique创建智能指针(C++14+支持,C++11可以直接用unique_ptr构造) unique_ptr<testStruct> obj = make_unique<testStruct>(); unique_ptr<wstring> strVal = make_unique<wstring>(); unique_ptr<vector<wstring>> vecVal = make_unique<vector<wstring>>(); unique_ptr<map<wstring, wstring>> mapVal = make_unique<map<wstring, wstring>>(); // 业务逻辑里直接用obj->nVal、strVal->size()这样的方式访问,和原始指针用法一致 // 不需要手动调用任何delete! // 当智能指针离开作用域时,会自动调用delete释放内存,同时自身会变成空状态 return 0; }
这种方式不仅代码更简洁,而且完全避免了手动管理内存的风险——你再也不用操心忘记delete、重复delete、指针置空这些问题了。
内容的提问来源于stack exchange,提问作者knkumar93
相关产品推荐
相关产品推荐

