new和malloc內部的實現方式有什麼區別?

自己重載new運算符的時候,是去調用malloc的;

那麼原始的new操作是怎麼寫的呢?

也是這樣嗎?

還是說和malloc有區別?


只說一點顯而易見的區別:

new的功能是在堆區新建一個對象,並返回該對象的指針。

所謂的【新建對象】的意思就是,將調用該類的構造函數,因為如果不構造的話,就不能稱之為一個對象。

而malloc只是機械的分配一塊內存,如果用mallco在堆區創建一個對象的話,是不會調用構造函數的

嚴格說來用malloc不能算是新建了一個對象,只能說是分配了一塊與該類對象匹配的內存而已,然後強行把它解釋為【這是一個對象】,按這個邏輯來,也不存在構造函數什麼事

同樣的,用delete去釋放一個堆區的對象,會調用該對象的析構函數

用free去釋放一個堆區的對象,不會調用該對象的析構函數

做個簡單的實驗即可明了

#include &
#include &

class TEST
{
private:
int num1;
int num2;
public:
TEST()
{
num1 = 10;
num2 = 20;
}
void Print()
{
std::cout &<&< num1 &<&< " " &<&< num2 &<&< std::endl; } }; int main(void) { // 用malloc()函數在堆區分配一塊內存空間,然後用強制類型轉換將該塊內存空間 // 解釋為是一個TEST類對象,這不會調用TEST的默認構造函數 TEST * pObj1 = (TEST *)malloc(sizeof(TEST)); pObj1-&>Print();

// 用new在堆區創建一個TEST類的對象,這會調用TEST類的默認構造函數
TEST * pObj2 = new TEST;
pObj2-&>Print();

return 0;
}
/*
運行結果:

-----------------------------
-842150451 -842150451 |
10 20 |
請按任意鍵繼續. . . |
-----------------------------

我們可以看到pObj1所指的對象中,欄位num1與num2都是垃圾值
而pObj2所指的對象中,欄位num1與num2顯然是經過了構造後的值
*/


實現上我所知的標準庫(libc++/clang, stdc++/gcc)的做法就是調 malloc.

區別是 new 失敗了會掉一個 handler 做補救, 該 handler 默認是 nullptr.

再一個是 new 失敗了會丟 bad_alloc(如果沒指定 nothrow 的話)

再一個是 C++ 不許有 size 為 0 的對象, 所以這樣的 new 會被強制轉為 1

malloc 的實現相當複雜. 請務必不要深究.

---------------------------------------

如 @很好 所說, 使用 new, 編譯器會生成一段做初始化的代碼. 但這段代碼對你並不可見.


簡單來說,

malloc: C函數。簡單的分配一段給定大小的內存給你返回一個指針,如果失敗,返回0。

new: C++函數,可以理解成兩步:1。malloc;2。如果需要的話,在那段內存上初始化對象(賦值或者調用構造函數)。


題主,你重載的不是new操作符,而是operator new()函數。new操作符在生成一個對象的時候一般分兩步,調用operator new()函數分配內存,然後再用構造函數初始化對象。

而operator new()的作用和malloc()幾乎是一樣的,都是為了分配內存,::operator new()內部實現的時候應該也是調用的malloc()來獲取內存,不過額外的添加了一些其他的處理步驟。


在stackoverflow上搜了一下:

[malloc/free new/delete的區別](c++ - What is the difference between new/delete and malloc/free?)

搬運工來了。。:

- new/delete

&>Allocate/release memory

1,Memory allocated from "Free Store"

2,Returns a fully typed pointer.

3,new (standard version) never returns a NULL (will throw on failure)

4,Are called with Type-ID (compiler calculates the size)

5,Has a version explicitly to handle arrays.

6,Reallocating (to get more space) not handled intuitively (because of copy constructor).

7,Whether they call malloc/free is implementation defined.

8,Can add a new memory allocator to deal with low memory (set_new_handler)

9,operator new/delete can be overridden legally

10,**constructor/destructor used to initialize/destroy the object**

- 分配/釋放內存

1,從free空間分配內存

2,返回一個完全類型的指針(因為你要指明是什麼類型的)

3,new如果分配失敗的話絕不會返回一個空指針NULL,而是會拋出失敗異常

4,用類型來申請就可以了(編譯器自動計算大小),(註:比如 `auto p=new int;`)

5,對處理數組有一個顯示的版本(可能是在分配一個數組的時候會特別的處理)

6,(不確定是否準確)會重新分配來獲取更大的空間而不是由於拷貝構造函數而直接處理(意會。。)

7,實現(new/delete)的時候就決定了是否會調用malloc/free函數

8,可以新增一個內存分配器來處理低可用內存(`set_new_handler`)

9,操作符new/delete可以被合法的覆蓋

10,**調用(這個類型的)構造函數和析構函數來初始化/刪除對象

(也就是說new/delete的是針對對象的!這個對象可以說int,double等,也可以是自定義的class)**

&>malloc/free

Allocates/release memory

1,Memory allocated from "Heap"

2,Returns a void*

3,Returns NULL on failure

4,Must specify the size required in bytes.

5,Allocating array requires manual calculation of space.

6,Reallocating larger chunk of memory simple (No copy constructor to worry about)

7,They will NOT call new/delete.

8,No way to splice user code into the allocation sequence to help with low memory.

9,malloc/free can NOT be overridden legally

- 1,內存來源於堆

2,返回的是`void*`類型的指針

3,如果分配失敗的話,會返回一個NULL指針(所以我們在程序裡面通過判斷是否為空檢測是否分配成功)

4,必須要指明需要多少Byte的空間!

5,分配數組需要人工計算需要多大空間

6,重新分配更大的內存,不需要考慮拷貝構造函數

7,這組函數不會調用new/delete

8,用戶代碼無法幫助解決低內存的問題

9,mallco/free不會被合法的覆蓋(無視?取消?)掉

繼續補充在網上看到的:

-

&>malloc與free是C++/C 語言的標準庫函數,new/delete 是C++的運算符。對於非內部數據類的對象而言,光用maloc/free 無法滿足動態對象的要求。對象在創建的同時要自動執行構造函數, 對象消亡之前要自動執行析構函數。由於malloc/free 是庫函數而不是運算符,不在編譯器控制許可權之內,不能夠把執行構造函數和析構函數的任務強加malloc/free。

這個很重要,new的是對象!

(從blog上copy下來的,是md格式,懶的改了)

博客:malloc/free new/delete的區別


推薦閱讀:

如何高效的學習Nginx源碼,汲取養分?
為什麼說goto是一種不好的用法?
如何用 C 語言畫一個「聖誕樹」?
如何評價C# 6的這個新特性?
怎樣減輕程序中 if 語句的依賴?

TAG:編程 | C編程語言 | C |