vc中new和delete操作符的重载

跟風遠走 提交于 2019-12-05 19:50:31

在C++中重载new和delete操作符可以给程序带来更灵活的存储控制,对于游戏设计等对效率要求较高的应用而言是必不可少的。一般的C++书籍中也会介绍它们的应用和实现,然而在VC中实现却有几个必须注意的地方,否则编译会出现问题。

1. 实现

首先,vc在每个自动生成的cpp文件中都会加入如下代码:

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

从上面红色的字体可以看出,这时的new在debug模式下被定义成了DEBUG_NEW,所以实现new函数的代码应该放在此定义之前,否则编译会报错。

那么DEBUG_NEW又是什么东西呢?在afx.h文件中可以找到答案:

#define DEBUG_NEW new(THIS_FILE, __LINE__)

因而,在debug模式下如果我们调用如下代码:

CWnd* pWnd = new CWnd;

就变成了

CWnd* pWnd = new(THIS_FILE, __LINE__) CWnd;

上面的代码相当于调用了new(sizeof(CWnd), THIS_FILE, __LINE__)函数,它的原型为:

void* operator new(size_t, LPCTSTR, int);

所以在debug模式下我们的new操作符必须定义为如上形式。

2. 几个问题

2.1 delete匹配问题

如果实现了void* operator new(size_t, LPCTSTR, int)操作符,最好是同时实现与之相对应的

void operator delete(void* p, LPCTSTR, int)

操作符,否则编译器会报一个警告错误:no matching operator delete found; memory will not be freed if initialization throws an exception。

2.2 成员new操作符重载

如果重载了类的new和delete操作符,必须将他们声明为静态成员。这是因为对于非静态的成员函数,编译器会在其末尾添加一个this参数;另外,调用new的时候,类还没有构造。以上都导致了对静态声明的要求。

2.3 全局new操作符重载

如果要重载全局的new和delete操作符,只需实现以下函数(release模式下):

inline void * __cdecl operator new (size_t size);
inline void __cdecl operator delete (void *p);

不需要进行声明,只要在某个地方实现上述函数,那么所有的new操作都会调用我们实现的函数进行。但在release模式下有个问题:new和delete的调用次数不一致。在我实现的一个测试程序中(vc6.0,缺省自动生成的多文档程序),new被调用了5次,而delete只被调用了3次,最开始两次调用的new操作没有相应的delete操作。不知道是不是调用了其他的delete原型。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!