1. 程式人生 > >vc中new和delete操作符的過載

vc中new和delete操作符的過載

在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