作者:LogM
本文原載於 https://segmentfault.com/u/logm/articles,不允許轉載~
8. 定製new和delete
-
8.1 條款49:瞭解new-handler的行爲
- new-handler相當於new的異常處理函數。new申請內存發生異常,調用new-handler處理,處理完了之後繼續嘗試new,如果還是出錯,繼續調用new-handler,以此反覆。
-
//標準庫對於new-handler是這麼寫的: //new_handler被定義成一個函數指針 //set_new_handler函數的參數是個指針,指向new無法分配足夠內存時應該調用的函數; //set_new_handler函數的返回值是個指針,指向set_new_handler之前設置的new_handler函數 namespace std { typedef void (*new_handler)(); new_handler set_new_handler(new_handler p) throw(); } //可以這樣使用set_new_handler void oufOfMem() { std::cerr << "Unalbe to new\n"; std::abort(); } int main() { std::set_new_handler(outOfMem); int * pBigArray = new int[10000000000L]; }
-
一般來說,new-handler函數會做以下事情的某幾件:
- a. 讓更多內存可被使用。使得再次嘗試new能成功。
- b. 安裝另一個new-handler。使用更強力的new-handler處理。
- c. 卸載new-handler。實在不行,卸載new-handler使new拋出異常。
- d. 拋出bad_alloc的異常。
- e. 退出程序。abort()或exit()。
-
8.2 條款50:瞭解new和delete的合理替換時機
- 這部分講的是:如果你覺得編譯器自帶的new和delete不好用,應該怎麼寫一個自定義的函數替換。
- 作者自己也提到了,要自定義new和delete不是簡單寫個函數就好了,內存的申請和釋放會涉及到計算機體系架構中比較底層的東西,比如"內存對齊"。所以重頭開始寫new和delete是比較複雜的,可以買現成的商業產品,或者在開源代碼上修改。
-
8.3 條款51:編寫new和delete時需要固守常規
- 條款50已經說明了,自定義new和delete比較複雜,非必要不建議重寫。
-
這部分講了自定義new和delete時需要注意的事項:
- operator new應該內含一個無窮循環,並在其中嘗試分配內存,分配不了,調用new-handler。
- operator new對0 bytes的內存申請,也需要正常返回指針。
- operator delete應該在收到null指針時不做任何事。
-
8.4 條款52:寫了placement new也要寫placement delete
-
Widget* pw = new Widget //這句話中總共有2個函數被調用:1.operator new分配內存;2.Widget的構造函數 //當調用Widget構造函數發生異常時,需要delete掉第一步new出來的內存 //如果使用C++自帶的new和delete,這個情況不需要用戶考慮;如果是自定義new和delete,需要用戶考慮
-