自己重寫operator new時,很重要的一點是函數提供的行為要和系統缺省的operator new一致。實際做起來也就是:要有正確的返回值;可用內存不夠時要調用出錯處理函數;處理好0字節內存請求的情況。此外,還要避免不小心隱藏了標準形式的new。
非類成員形式的operator new的偽代碼:
void * operator new(size_t size) // operator new還可能有其它參數
{
if (size == 0) // 處理0字節請求時,
{
size = 1; // 把它當作1個字節請求來處理
}
while (1)
{
分配size字節內存;
if (分配成功)
return (指向內存的指針);
// 分配不成功,找出當前出錯處理函數
new_handler globalhandler = set_new_handler(0);
set_new_handler(globalhandler);
if (globalhandler) (*globalhandler)();
else throw std::bad_alloc();
}
}
為特定類寫的new往往沒有考慮該類被繼承的情況,使用sizeof(父類)獲得大小,但是如果發生子類調用父類的new時,往往
會出錯,子類的size往往大于父類的size。最好父類的new應該這么寫:
void * base::operator new(size_t size)
{
if (size != sizeof(base)) // 如果數量“錯誤”,讓標準operator new,精華部分。
return ::operator new(size); // 去處理這個請求
//
... // 否則處理這個請求
}
對于operator delete(以及它的伙伴operator delete[]),情況更簡單。所要記住的只是,c++保證刪除空指針永遠是安全的,所以你要充分地應用這一保證。
下面是非類成員形式的operator delete的偽代碼:
void operator delete(void *rawmemory)
{
if (rawmemory == 0) return; //如果指針為空,返回
//
釋放rawmemory指向的內存;
return;
}
這個函數的類成員版本也簡單,只是還必須檢查被刪除的對象的大小。假設類的operator new將“錯誤”大小的分配請求轉給::operator new,那么也必須將“錯誤”大小的刪除請求轉給::operator delete:
void base::operator delete(void *rawmemory, size_t size)
{
if (rawmemory == 0) return; // 檢查空指針
if (size != sizeof(base)) // 如果size"錯誤",
{
::operator delete(rawmemory); // 讓標準operator來處理請求
return;
}
釋放指向rawmemory的內存;
return;
}
有關operator new和operator delete(以及他們的數組形式)的規定不是那么麻煩,重要的是必須遵守它。只要內存分配程序支持new-handler函數并正確地處理了零內存請求,就差不多了;如果內存釋放程序又處理了空指針,那就沒其他什么要做的了。至于在類成員版本的函數里增加繼承支持,那將很快就可以完成。