#include <iostream> #include <string> using namespace std; class Foo { public: int _id; int _data; int _num; public: // 若是沒有重載的成員函數則調用全局版本 static void *operator new(size_t size); static void operator delete(void *pdead, size_t size); static void *operator new[](size_t size); static void operator delete[](void *pdead, size_t size); Foo() : _id(0) { cout << "default ctor.this=" << this << " id=" << _id << endl; } Foo(int i) : _id(i) { cout << "ctor. this=" << this << " id=" << _id << endl; } // virtual ~Foo() { cout << "dtor. this=" << this << " id=" << _id << endl; } }; void *Foo::operator new(size_t size) { Foo *p = (Foo*)malloc(size); cout << "Foo::operator new(), size=" << size << "\t return: " << p << endl; return p; } void Foo::operator delete(void *pdead, size_t size) { cout << "Foo::operator delete(), pdead= " << pdead << " size= " << size << endl; free(pdead); } void *Foo::operator new[](size_t size) { Foo *p = (Foo*)malloc(size); cout << "Foo::operator new[](), size=" << size << "\t return: " << p << endl; return p; } void Foo::operator delete[](void *pdead, size_t size) { cout << "Foo::operator delete[](), pdead= " << pdead << " size= " << size << endl; free(pdead); } int main() { cout << "sizeof(Foo)=" << sizeof(Foo) << endl; cout << "============" << endl; Foo *p = new Foo(7); delete p; cout << "============" << endl; Foo* pArray = new Foo[5]; delete [] pArray; return 0; }
當 Foo 無虛析構函數時,輸出:
ios
sizeof(Foo)=12 // 注意這裏 !! ============ Foo::operator new(), size=12 return: 0x7617b0 ctor. this=0x7617b0 id=7 dtor. this=0x7617b0 id=7 Foo::operator delete(), pdead= 0x7617b0 size= 12 ============ Foo::operator new[](), size=68 return: 0x7617b0 default ctor.this=0x7617b8 id=0 default ctor.this=0x7617c4 id=0 default ctor.this=0x7617d0 id=0 default ctor.this=0x7617dc id=0 default ctor.this=0x7617e8 id=0 dtor. this=0x7617e8 id=0 dtor. this=0x7617dc id=0 dtor. this=0x7617d0 id=0 dtor. this=0x7617c4 id=0 dtor. this=0x7617b8 id=0 Foo::operator delete[](), pdead= 0x7617b0 size= 68
當 Foo 有虛析構函數時,輸出:
函數
sizeof(Foo)=16 // 注意這裏 !! ============ Foo::operator new(), size=16 return: 0xfb8088 ctor. this=0xfb8088 id=7 dtor. this=0xfb8088 id=7 Foo::operator delete(), pdead= 0xfb8088 size= 16 ============ Foo::operator new[](), size=84 return: 0xfb8088 default ctor.this=0xfb808c id=0 default ctor.this=0xfb809c id=0 default ctor.this=0xfb80ac id=0 default ctor.this=0xfb80bc id=0 default ctor.this=0xfb80cc id=0 dtor. this=0xfb80cc id=0 dtor. this=0xfb80bc id=0 dtor. this=0xfb80ac id=0 dtor. this=0xfb809c id=0 dtor. this=0xfb808c id=0 Foo::operator delete[](), pdead= 0xfb8088 size= 84
int main() { cout << "sizeof(Foo)=" << sizeof(Foo) << endl; cout << "============" << endl; Foo *p = ::new Foo(7); // 注意這裏 !! ::delete p; cout << "============" << endl; Foo* pArray = ::new Foo[5]; // 注意這裏 !! ::delete[] pArray; return 0; }
當 Foo 無虛析構函數時,輸出[類中重載版本 new / delete 未被調用]:
測試
sizeof(Foo)=12 ============ ctor. this=0x7617b0 id=7 dtor. this=0x7617b0 id=7 ============ default ctor.this=0x7617b8 id=0 default ctor.this=0x7617c4 id=0 default ctor.this=0x7617d0 id=0 default ctor.this=0x7617dc id=0 default ctor.this=0x7617e8 id=0 dtor. this=0x7617e8 id=0 dtor. this=0x7617dc id=0 dtor. this=0x7617d0 id=0 dtor. this=0x7617c4 id=0 dtor. this=0x7617b8 id=0
當 Foo 有虛析構函數時,輸出[類中重載版本 new / delete 未被調用]:
this
sizeof(Foo)=16 ============ ctor. this=0xfb8088 id=7 dtor. this=0xfb8088 id=7 ============ default ctor.this=0xfb808c id=0 default ctor.this=0xfb809c id=0 default ctor.this=0xfb80ac id=0 default ctor.this=0xfb80bc id=0 default ctor.this=0xfb80cc id=0 dtor. this=0xfb80cc id=0 dtor. this=0xfb80bc id=0 dtor. this=0xfb80ac id=0 dtor. this=0xfb809c id=0 dtor. this=0xfb808c id=0
咱們能夠重載 class member operator new(), 寫出多個版本,前提是每個版本的聲明都必須具備獨特的參數列表,其中第一個參數必須是 size_t, 其他參數以 new 所指定的 placement arguments 爲初值。 出現於 new(...) 小括號內的即是所謂的 placement argument。spa
Foo *pf = new (300, 'c')Foo;
咱們也能夠重載 class member operator delete(), 寫出多個版本。但它們毫不會被 delete 調用【void operator delete(void*, size_t)
版本被調用】。只有當 new 所調用的構造函數拋出異常,纔會調用這些重載版本對應的 operator delete()。它只可能這樣被調用,主要用來歸還未能徹底建立成功的對象所佔用的內存空間。指針
#include <iostream> using namespace std; class Bad { }; class Foo { public: Foo() { cout << "Foo::Foo()" << endl; } Foo(int) { cout << "Foo::Foo(int)" << endl; throw Bad(); // 故意在這裏拋出異常,測試 placement operator delete } // (1) 通常的 operator new() 重載函數 void *operator new(size_t size) { cout << "operator new(size_t size), size= " << size << endl; return malloc(size); } // (2) 標準庫已經提供的 placement new() 的重載形式 // (這裏模擬 standard placement new 的動做, just return ptr) void *operator new(size_t size, void *start) { cout << "operator new(size_t size, void *start), size= " << size << endl; return start; } // (3) 一個嶄新的 placement new void *operator new(size_t size, long extra) { cout << "operator new(size_t size, long extra), size= " << size << ' ' << extra << endl; return malloc(size + extra); } // (4) 又一個 placement new void *operator new(size_t size, long extra, char init) { cout << "operator new(size_t size, long extra, char init), size= " << size << ' ' << extra << ' ' << init << endl; return malloc(size + extra); } // (5) 這又是一個 placement new, 但故意寫錯第一參數 type (它必須是 size_t 以知足正常的 operator new) //! void *operator new(long extra, char init) { // error: 'operator new' takes type size_t ('unsigned int') as first parameter //! cout << "op-new(long, char)" << endl; //! return malloc(extra); //! } // 如下是搭配上述 placement new 的各個 called placement delete. // 當構造函數拋出異常,這裏對應的 operator (placement) delete 就會調用. // 應該是要負責釋放其搭檔兄弟 (placement new) 分配所得的內存. // (1) 這個就是通常的 operator delete() 的重載 void operator delete(void* ptr, size_t) { cout << "operator delete(void*, size_t)" << endl; free(ptr); } // (2) 這個是對應上述的 (2) void operator delete(void *ptr, void*) { cout << "operator delete(void *ptr, void*)" << endl; free(ptr); } // (3) 這個是對應上述的 (3) void operator delete(void *ptr, long) { cout << "operator delete(void *ptr, long)" << endl; free(ptr); } // (4) 這個是對應上述的 (4) void operator delete(void *ptr, long, char) { cout << "operator delete(void *ptr, long, char)" << endl; free(ptr); } private: int m_i; }; int main() { Foo start; Foo *p1 = new Foo; // op-new(size_t) Foo *p2 = new (&start)Foo; // op-new(size_t, void*) Foo *p3 = new (100)Foo; // op-new(size_t, long) Foo *p4 = new (100, 'a')Foo; // op-new(size_t, long, char) delete p1; // 注意這裏!! delete p2; // 注意這裏!! delete p3; // 注意這裏!! delete p4; // 注意這裏!! return 0; }
輸出:code
Foo::Foo() operator new(size_t size), size= 4 Foo::Foo() operator new(size_t size, void *start), size= 4 Foo::Foo() operator new(size_t size, long extra), size= 4 100 Foo::Foo() operator new(size_t size, long extra, char init), size= 4 100 a Foo::Foo() operator delete(void*, size_t) operator delete(void*, size_t) operator delete(void*, size_t) operator delete(void*, size_t)
int main() { Foo start; Foo *p5 = new (100)Foo(1); // op-new(size_t, long) op-del(void*, long) Foo *p6 = new (100, 'a')Foo(1); // Foo *p7 = new (&start)Foo(1); // Foo *p8 = new Foo(1); // return 0; }
輸出:對象
Foo::Foo() operator new(size_t size, long extra), size= 4 100 Foo::Foo(int) terminate called after throwing an instance of 'Bad' // 構造函數拋出異常
說明
以上使用 mingw81 測試,operator delete(void *, long) 並未被調用;但G2.9確實有調用。