在C++中重載new和delete操做符能夠給程序帶來更靈活的存儲控制,對於遊戲設計等對效率要求較高的應用而言是必不可少的。通常的C++書籍中也會介紹它們的應用和實現,然而在VC中實現卻有幾個必須注意的地方,不然編譯會出現問題。函數
首先,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操做符必須定義爲如上形式。
若是實現了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。
若是重載了類的new和delete操做符,必須將他們聲明爲靜態成員。這是由於對於非靜態的成員函數,編譯器會在其末尾添加一個this參數;另外,調用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原型。