new 與 malloc 的區別

申請的內存所在位置

  • 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沒有這樣直觀的配套設施來擴充內存。

總結
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章