beat365唯一网址-正规365娱乐平台-365bet线路检测中心

记录时光的故事

C++指针编程你要小心的陷阱——如何优雅的释放指针void*

分类: 365bet线路检测中心 时间: 2025-08-20 22:43:35 作者: admin 阅读: 4338
C++指针编程你要小心的陷阱——如何优雅的释放指针void*

C++相对C语言的改进就是引入了面向对象操作,支持函数重载、类继承、模板、异常处理等等概念。在C++中,一般用函数模板来操作释放指针,这样的好处是可以进行类型检查。

view plai

// 删除数组

template

inline void safe_delete(T *&target) {

if (nullptr != target) {

delete target;

target = nullptr;

}

}

// 删除数组指针

template

inline void safe_delete_arr(T *&target) {

if (nullptr != target) {

delete[] target;

target = nullptr;

}

}

三、void *指针问题

在C、C++ 中,void * 指针可以转换为任意类型的指针类型,在删除void*指针时编译器往往会发出如下警告

warning: deleting 'void*' is undefined [enabled by default]

翻译:警告:删除“void *”指针可能引发未知情况(默认打开警告)

永远记住,在C、C++开发中绝对不能忽视警告,一定要重视警告,最好消除警告。有些警告无关紧要,有些警告却是bug的根源;删除void *指针的警告就属于后面一种情况,可能引起严重的bug而且难以发现:

1. 使用delete pointer; 释放void指针void *,系统会以释放普通指针(char, short, int, long, long long)的方式来释放void *指向的内存空间;

2. 如果void *指向一个数组指针,那么由于释放指针时用了delete pointer从而导致内存泄漏,释放指针正确做法是delete[] pointer;

3. 如果void *指向一个class类,那么系统由于认为void *指向一个普通的内存空间,所以释放指针时系统class的析构函数不会调用;

释放void *的解决方案:将void *转换为原来类型的指针,然后再调用delete释放指针,如果原来的指针是数组指针,那么必须使用delete []删除指向的内存空间。

在C++中我们可以使用模板定义内联函数:

template

inline void safe_delete_void_ptr(void *&target) {

if (nullptr != target) {

T* temp = static_cast(target);

delete temp;

temp = nullptr;

target = nullptr;

}

}

调用方法

view plain

cop

int *psample = new int(100);

safe_delete_void_ptr(psample);

利用模板实例化参数统一简化过程。

测试代码

safe_delete_demo.cpp

#include

#include

#include

#include

template

inline void safe_delete(T *&target) {

if (nullptr != target) {

delete target;

target = nullptr;

}

}

template

inline void safe_delete_void_ptr(void *&target) {

if (nullptr != target) {

T* temp = static_cast(target);

delete temp;

temp = nullptr;

target = nullptr;

}

}

class A {

public:

A(std::string name) {

this->name = name;

};

virtual ~A() {

std::cout<<"base class A's destructor"<<", name: "<name<

};

public:

std::string name;

};

class AChild: public A {

public:

AChild(std::string name, std::string school)

: A(name){

this->school = school;

};

~AChild() {

std::cout<<"child class AChild's destructor"<<", name: "<name

<<", school: "<school<

};

public:

std::string school;

};

int main(int argc, char *argv[]) {

// 测试safe_delete释放普通类指针

std::cout<<"safe_delete pointer of type AChild"<

AChild *a1 = new AChild("jacky", "Shenzhen University");

safe_delete(a1);

std::cout<

// 测试safe_delete释放void*指针

std::cout<<"safe_delete pointer of type void *"<

void *vp = new AChild("Polyn", "Southern University of Science and Technology");

safe_delete(vp);

std::cout<

// 测试safe_delete_void_ptr释放模板实例化为基类的void*指针

std::cout<<"safe_delete_void_ptr pointer of type void * ==> A *"<

void *vpA = new AChild("Heral", "Renmin University of China");

safe_delete_void_ptr(vpA);

std::cout<

// 测试safe_delete_void_ptr释放模板实例化为子类的void*指针

std::cout<<"safe_delete_void_ptr pointer of type void * ==> AChild *"<

void *vpAChild = new AChild("pevly", "Southeast University");

safe_delete_void_ptr(vpAChild);

return 0;

}

编译及运行

$ g++ -std=c++11 safe_delete_demo.cpp

safe_delete_demo.cpp: In instantiation of 'void safe_delete(T*&) [with T = void]':

safe_delete_demo.cpp:59:16: required from here

safe_delete_demo.cpp:9:9: warning: deleting 'void*' is undefined [enabled by default]

delete target;

$ ./a.out

safe_delete pointer of type AChild

child class AChild's destructor, name: jacky, school: Shenzhen University

base class A's destructor, name: jacky

safe_delete pointer of type void *

safe_delete_void_ptr pointer of type void * ==> A *

child class AChild's destructor, name: Heral, school: Renmin University of China

base class A's destructor, name: Heral

safe_delete_void_ptr pointer of type void * ==> AChild *

child class AChild's destructor, name: pevly, school: Southeast University

base class A's destructor, name: pevly

通过测试用例我们可以看出。

1. 使用safe_delete释放明确的类会自动触发析构函数(如果析构函数为虚函数,那么先调用子类的析构函数再调用子类的直接基类的析构函数); 2. 使用safe_delete释放void*指针指向的类时,不会触发对应类的析构函数;

3. 如果使用safe_delete_void_ptr内联函数释放void*指针,那么由于在释放指针前,函数会将void*指针转换为特定类型的函数指针,所以最终能够触发调用析构函数,并且不影响虚类的释放行为。

本文转自: http://blog.csdn.net/sweettool/article/details/77688337

相关文章

巧用分类汇总 快速统计数据
如何制作帆船帆布(织物帆船的制作过程)
ahc和sum哪个好用? sum护肤品13岁可以用吗?
王者荣耀:官方公布吕布天魔缭乱优化细节,模型调整回城更霸气,14日返场,如何评价?
完美世界官方合作虚拟物品交易伙伴
j罗带伤上世界杯(J罗高光一战比肩三大传奇 为世界杯而生的男人名不虚传)