申請的內存所在位置
- new 操作符從自由存儲區(free store)上爲對象動態分配內存空間,而 malloc 函數從堆上動態分配內存。
- 自由存儲區是C++基於new操作符的一個抽象概念,凡是通過new操作符進行內存申請,該內存即爲自由存儲區。
- 堆是操作系統中的術語,是操作系統所維護的一塊特殊內存,用於程序的內存動態分配,C語言使用malloc從堆上分配內存,使用free釋放已分配的對應內存。
- 那麼自由存儲區是否能夠是堆(問題等價於new是否能在堆上動態分配內存),這取決於operator new 的實現細節。自由存儲區不僅可以是堆,還可以是靜態存儲區,這都看operator new在哪裏爲對象分配內存。
返回類型安全性
- new 操作符內存分配成功時,返回的是對象類型的指針,類型嚴格與對象匹配,無須進行類型轉換,故 new 是符合類型安全性的操作符。
- malloc 函數內存分配成功時,返回 void *,需要通過強制類型轉換將 void * 指針轉換成我們需要的類型。
內存分配失敗時的返回值
- new內存分配失敗時,會拋出bac_alloc異常,它不會返回NULL。
- malloc內存分配失敗時,返回NULL。
是否需要指定內存大小
- 使用 new 操作符申請內存分配時無須指定內存塊的大小,編譯器會根據類型信息自行計算。
- 使用 malloc 函數申請內存分配時需要顯式地指出所需內存的大小。
是否調用構造函數/析構函數
- 使用new操作符來分配對象內存時會經歷三個步驟:
- 第一步:調用operator new 函數(對於數組是operator new[])分配一塊足夠大的,原始的,未命名的內存空間以便存儲特定類型的對象。
- 第二步:編譯器運行相應的構造函數以構造對象,併爲其傳入初值。
- 第三步:對象構造完成後,返回一個指向該對象的指針。
- 使用delete操作符來釋放對象內存時會經歷兩個步驟:
- 第一步:調用對象的析構函數。
- 第二步:編譯器調用operator delete(或operator delete[])函數釋放內存空間。
- new/delete會調用對象的構造函數/析構函數來完成對象的構造/析構。而malloc則不會。
對數組的處理
- C++提供了new[]與delete[]來專門處理數組類型,使用new[]分配的內存必須使用delete[]進行釋放。
- new對數組的支持體現在它會分別調用構造函數初始化每一個數組元素,釋放對象時爲每個對象調用析構函數。注意delete[]要與new[]配套使用,不然會找出數組對象部分釋放的現象,造成內存泄漏。
- 至於malloc,它並不知道你在這塊內存上要放的數組還是啥別的東西,反正它就給你一塊原始的內存,再給你個內存的地址就完事。所以如果要動態分配一個數組的內存,還需要我們手動自定數組的大小。
是否相互調用
- operator new /operator delete的實現可以基於malloc。
- malloc的實現不可以去調用new。
是否能被重載
- opeartor new/operator delete可以被重載。
- malloc/free 不允許重載。
是否能直觀地重新分配內存
- 使用malloc分配的內存後,如果在使用過程中發現內存不足,可以使用realloc函數進行內存重新分配實現內存的擴充。realloc先判斷當前的指針所指內存是否有足夠的連續空間,如果有,原地擴大可分配的內存地址,並且返回原來的地址指針;如果空間不夠,先按照新指定的大小分配空間,將原有數據從頭到尾拷貝到新分配的內存區域,而後釋放原來的內存區域。
- new沒有這樣直觀的配套設施來擴充內存。
總結