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函數的代碼應該放在此定義以前,不然編譯會報錯。this

那麼DEBUG_NEW又是什麼東西呢?在afx.h文件中能夠找到答案:spa

#define DEBUG_NEW new(THIS_FILE, __LINE__)debug

於是,在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原型。

相關文章
相關標籤/搜索