為 class 重載 operator new 時必須定義為類的靜态函數 ( 預設為 static 函數 ) 。重載 operator new 更多的是為了提高程式效率,比如使用靜态記憶體代替動态配置設定,啟用小對象配置設定器等。但是要正确重載類域的 operator new 并不容易,有很多規則需要注意: 1) 總是成對提供 new/delete ; 2) 如重載 operator new 一定要同時提供标準形式的 new 。舉例:
class T {
static void* operator new(std::size_t);
static void* operator new(std::size_t, CustomAllocator&);
static void operator delete(void*, std::size_t);
};
T* p = new(alloc) T;
上述代碼将被編譯器展成下述代碼 ( 猜測,如果有高人知道如何檢視編譯器生成的中間代碼,煩請告知)
// compiler-generated code for T* p = new(alloc) T;
//
void* __compilerTemp = T::operator new (sizeof(T), alloc); // 1
T* p;
try {
p = new (__compilerTemp) T; // 2 // construct a T at address __compilerTemp
}
catch(...) { // constructor failed, attention here…
T::operator delete (__compilerTemp, sizeof(T), alloc); // 3
throw;
注釋 1 : operator new 用于配置設定記憶體, new 的第一步驟;
注釋 2 : placement new 用于在于位址上建構對象,也就是調用 T 的構造函數。
注釋 3 :與 operator new 配套的 operator delete 。
C++ 标準規定:當且僅當 operator delete 的重載存在時,以上代碼才能生成。否則,在構造函數失敗的情況下,代碼不會調用 operator delete 。也就是說,如果構造函數抛異常,記憶體将洩漏。
這意味着:當提供 void* operator new(parms) 重載時,必須同時提供 void operator delete(void*, parms), 這裡參數清單的第一個參數總為 std::size_t 。 對于 operator new[] 也是如此。例外,對于 placement new 由于并不實際配置設定記憶體,可不重載相應的 operator delete 。
避免隐藏全局的operator new 和基類重定義的 operator new
前面已經提到過 C++ 名字查找規則,對于重載的 operator new 也需要遵循此規則。當類中重載 operator new ,那麼全局的operator new 将被隐藏;如果派生類重載 operator new ,那麼基類的版本将被隐藏。由于 placement new 大量用于 STL 的優化中,故一定要避免隐藏 placement new 。隐藏 operator new 的這類錯誤編譯器會給出提示。
重載 opeartor new 并避免隐藏全局 operator new 的途徑:
1) 對于基類重載的 operator new ,使用 using 來導入相應名字。
class C : public B {// …
public:
static void* operator new(size_t, MemoryPool&); // private version
using B::operator new;
};
2) 對一般重載 operator new 的類,除了提供私有版本外,應該對所有全局 operator new 形式提供轉換函數。如下:
class C {// …
static void* operator new(size_t, MemoryPool&); // private version
static void* operator new(std::size_t s) {
return ::operator new(s); // global version
}
static void* operator new(std::size_t s, std::nothrow_t nt) throw() {
return ::operator new(s, nt);
static void* operator new(std::size_t s, void* p) {
return ::operator new(s, p);
相關文章:
<a href="http://www.cnblogs.com/zhenjing/archive/2011/01/archive/2011/01/10/3_kind_new.html">深入new/delete:New的3種形态</a>
<a href="http://www.cnblogs.com/zhenjing/archive/2011/01/archive/2011/01/10/groble_new.html">深入new/delete:Operator new的全局重載</a>
<a href="http://www.cnblogs.com/zhenjing/archive/2011/01/archive/2010/12/02/override_overwrite_overload.html">派生類函數的重實作規則(override-覆寫)</a>
---------------------------------------------------
歡迎轉載,請注明作者和出處
本文轉自 zhenjing 部落格園部落格,原文連結:http://www.cnblogs.com/zhenjing/archive/2011/01/17/class_new.html ,如需轉載請自行聯系原作者