參考資料:html
http://en.cppreference.com/w/cpp/memory/new/operator_newjava
http://en.cppreference.com/w/cpp/memory/new/operator_deletec++
http://www.wuzesheng.com/?p=840數組
http://www.blogjava.net/bacoo/archive/2008/07/13/214612.html函數
#include <cstdio> #include <cstdlib> void * operator new(size_t unSize) { printf("operator new called\n"); return malloc(unSize); } void * operator new[](size_t unSize) { printf("operator [] called\n"); return malloc(unSize); } void * operator new(size_t unSize, int nLine, const char * pFunc) { printf("operator new called, line: %d, func: %s\n", nLine, pFunc); return malloc(unSize); } //注意:c++14才支持全局delete或delete【】有多個參數,參看參考資料2.下面兩個delete不會覆蓋全局的。 void operator delete(void * pMem,size_t unSize) { printf("delete1: %u\n", unSize); free(pMem); } void operator delete[](void * pMem, size_t unSize) { printf("delete[]: %u\n", unSize); free(pMem); } class A { public: A(int a = 0) : _a(a) { printf("constructor called\n"); } virtual ~A() { printf("~A()\n"); } void * operator new(size_t unSize) { printf(" calledA\n"); return malloc(unSize); } //注意:可是支持自定義類型操做符new或delete重載支持size_t參數。即要刪除對象的大小delete,要刪除對象數組大小delete[].。
void operator delete(void * pMem, size_t unSize) { printf("delete2: %u\n", unSize); free(pMem); } void operator delete[](void * pMem, size_t unSize) { printf("delete[]: %u\n", unSize); free(pMem); } private: int _a; }; class B: public A { public: //隱式的爲靜態函數。 void * operator new(size_t unSize, int nLine, const char * pFunc) { printf("operator new called, line: %d, fileB: %s\n", nLine, pFunc); printf("operator new: %u\n", unSize); //_b=0; return malloc(unSize); } ~B() { printf("~B()\n"); } int _b; int _bb; }; int main() { A * pA = new A(10); printf("#######\n"); A * pB = new (__LINE__, __FILE__) B(); printf("#######\n"); A * szA = new A[10]; B *szB = new B[10]; printf("#######\n"); delete pA; printf("#######\n"); delete pB; printf("#######\n"); delete [] szA; printf("#######\n"); delete [] szB; printf("#######\n");
//下面兩個不是自定義類,沒有類重載new.delete故只能調用全局的,本程序全局不支持size_t參數,故只能調用標準C++中的全局operate delete.故不會打印信息。 char * pC = new char[10]; delete [] pC;
char *pu = NULL;
delete pu;
}
gcc下運行結果:spa
calledA constructor called ####### operator new called, operator new: 16 constructor called ####### operator [] called constructor called constructor called constructor called constructor called constructor called constructor called constructor called constructor called constructor called constructor called operator [] called constructor called constructor called constructor called constructor called constructor called constructor called constructor called constructor called constructor called constructor called ####### ~A() delete2: 8 ####### ~B() ~A() delete2: 16 ####### ~A() ~A() ~A() ~A() ~A() ~A() ~A() ~A() ~A() ~A() delete[]: 84//注意84=4+8*10,數組分配的堆空間,第一個int空間放數組個數,接下來順序放對象
####### ~B() ~A() ~B() ~A() ~B() ~A() ~B() ~A() ~B() ~A() ~B() ~A() ~B() ~A() ~B() ~A() ~B() ~A() ~B() ~A() delete[]: 164 ####### operator [] called //調用覆蓋的全局函數operate new [],打印信息。
//delete[]調用全局的。
說明:1 在vs中類中delete[]的size_t是8和16.不一樣編譯器結果不一樣。理論上應該是數組大小*類型字節。.net
2 若是基類有virtual析構函數,則傳給operator delete的大小講個怒被刪除指針所指對象的動態類型而變化,若是沒有聲明爲virtual,那麼經過基類指針刪除指向派生類對象,大小爲基類大小。代理
總結:指針
1 malloc只是C函數,內部應該是使用相似deepalloc等,主要功能是分配原始內存,返回void*類型,須要顯示轉換爲對應對象 類型指針。沒有調用對象構造函數。C中函數原本就沒有類沒有構造函數。code
free釋放回收堆空間。
2 C++中的new 和delete是操做符,A * pA = new A(10)分別調用下面兩步:
先調用void * operator new(size_t unSize) (調用順序:那個有就調用那個:類中重載了就調用類的,而後全局重載,最後是C++源碼中的全局函數)分配原始內存,未初始化的。裏面能夠調用malloc或者相似deapalloc來分配內存。
在調用A的構造函數,用初始化參數初始化。
delete pA;也分兩步:
先調用A析構函數;
在調用void operator delete(void * pMem)(調用順序同上面operator new),釋放內存。可調用free實現或者其餘實現。
3 operator new,operator delete隱式靜態函數,寫不寫static都是靜態的。
爲何必須是靜態的呢?由於他們要麼在構造對象前使用要麼在析構後使用。屬於類的函數,不是對象的函數。
4 operator new中傳入的大小是怎麼得到的呢,我以爲相似於sizeof(類型名)
關於sizeof不須要實例對象,我以爲類爲實例化編譯器不會給成員變量分配空間,但應該有個地方放的聲明,標明變量類型等。
還有,sizeof大小不包括靜態成員變量,靜態變量通常放在靜態區,不屬於對象。沒有成員變量的類大小爲1,有虛函數就要多4個字節(虛函數表指針)。
最後小結一下,new 和delete都是內建的操做符,語言自己所固定了,沒法從新定製。但它所調用的內存分配/釋放的函數,即operator new和operator delete能夠被重載
ps:
從彙編代碼可看出:對單個堆對象調用delete和對堆對象數組調用delete[]能夠發現,兩種狀況最主要的差異是在調用析構代理函數時傳遞的對象首地址,用delete析構單個對象是傳進的堆空間首地址(也是堆對象首地址),而用delete[]析構對象數組時傳遞的是偏移堆空間首地址4byte處內存地址(即堆空間中第一個對象首地址,前四個字節是個int型,放的數組大小,即對象個數)。所以,在釋放單個對象時調用delete[],或者釋放對象數組時調用delete,都會形成錯誤,應該配對使用。