當咱們建立一個new表達式時,會發生兩件事。首先使用operator new()分配內存,而後調用構造函數。在delete表達式裏,調用了析構函數,而後使用operator delete()釋放內存。咱們沒法控制構造函數與析構函數的調用,可是能夠改變內存分配函數operator new()和operator delete().ios
在使用系統內置的new和delete的內存分配系統是爲了通用的目的而設計的,可是在特殊的情形下,它並不能知足需求。有時候咱們爲了改善程序的效率,咱們會重載operator new和operator delete. 也許要建立和銷燬一個特定的類的很是多的對象以致於這個運算變成了速度的瓶頸。因此此時咱們會選擇重載new和delete.函數
重載new和delete的理由還有防止內存碎片:分配大小不一樣的內存可能會在堆上產生不少碎片,以致於很快用完內存。雖然內存可能還有,但因爲都是碎片,也就找不到足夠大的內存知足需求。經過爲特定類建立本身的內存分配器,能夠確保這種狀況不會發生。spa
注意:咱們雖然重載了new和delete,其實咱們只是改變了內存分配和釋放的部分,而內存構造函數和析構函數調用的部分沒有改變。設計
當operator new()找不到足夠大的內存塊來安排對象時,將對有一個特殊的函數被調用,這個函數是new-handler。new-handler的默認的動做是產生一個異常(exception)指針
1 #include<iostream> 2 #include<cstdlib> 3 #include<new> 4 using namespace std; 5 int count=0; 6 7 void out_of_memory(){ 8 cerr<<"memory exhausted after"<<count<<"allocations!"<<endl; 9 exit(1); 10 11 } 12 13 int main(){ 14 set_new_handler(out_of_memory); 15 while(1){ 16 count++; 17 new int[1000]; 18 } 19 20 }
上面的代碼就是在內存耗盡時,new operator操做符調用new-handler函數out_of_memory。new-handler函數必須沒有參數,返回值必須爲void。那麼咱們在重載operator new時,也可改變用完內存時的行爲,一種方法即便經過new-handler函數實現。code
重載new和delete與重載別的運算符同樣,能夠經過全局函數重載,也能夠經過對特定的類的成員函數重載。固然經過全局函數重載new和delete是很是極端的作法,不建議這樣作,雖然語法上是容許的。由於經過全局函數重載new和delete,那麼編譯器默認的版本就不能再使用了。對象
重載new和delete語法,首先重載的new必須有一個size_t參數,這個參數是編譯器產生並傳遞給咱們,它是要分配內存的對象的長度。必須返回一個執行那個等於或者大於這個長度的對象指針,若是沒有找到存儲單元,則返回一個0.若是真沒有找到存儲單元,不能僅僅返回0,也許還應該作一些諸如調用new-handler或者產生一個void*的異常信息。 重載的new operator()要返回一個void*指針。operator delete()的參數也是一個void*指針,參數之因此是一個void*指針,是由於它是在調用析構函數後獲得的指針,析構函數從存儲單元裏移除對象。opreator delete的返回類型是void。blog
1 #include<cstdio> 2 #include<cstdlib> 3 using namespace std; 4 5 void* operator new(size_t sz){//重載的new 6 printf("operator new: %d\n",sz); 7 void* m= malloc(sz); 8 if (!m) 9 puts("out of memory"); 10 return m; 11 } 12 13 void operator delete(void* m){//重載的delete 14 puts("operaor delete"); 15 free(m); 16 } 17 18 class S{ 19 int i[100]; 20 public: 21 S(){ puts("S::S()"); } 22 ~S(){ puts("S::~S()"); } 23 24 }; 25 26 int main(){ 27 puts("creating & destorying an int"); 28 int* p = new int(42); 29 delete p; 30 puts("creating & destorying an s"); 31 S* s = new S; 32 delete s; 33 puts("creating & destorying an S[3]"); 34 S* sa = new S[3]; 35 delete[] sa; 36 return 0; 37 }