C與C++的區別(2)——new和malloc的區別

一、本質區別

在C++中引入更多的關鍵字,比如:new和delete;
而malloc和free是庫函數,需要頭文件的支持;

 

二、申請的空間所在的位置

new關鍵字爲對象分配的空間在自由存儲區內。而molloc是從上分配內存;

C/C++內存通常分爲:堆、棧、自由存儲區、全局/靜態存儲區、常量存儲區;

自由存儲區:是C++中通過new和delete動態分配和釋放對象的抽象概念;operator new的底層大多由malloc實現,new和delete是可以C++中的關鍵字,可以對其進行重載(operator new),當new被重載時,內部實現並非只有malloc,此時的內存空間就和堆不同了,這是一塊組合的內存空間。

堆:C語言和操作系統的術語,堆是操作系統維護的特殊的一種內存。

 

三、返回類型

new運算符返回的是對象類型的指針,是一個確定性的類型,類型嚴格與對象匹配,無須進行類型轉換,故new滿足安全性;而malloc的返回值是一個void*類型,是一個不確定的類型,需要進行類型的轉換。

類型安全很大程度上可以等價於內存安全,類型安全的代碼不會試圖分配在自己沒被授權的內存區域。

 

四、內存分配失敗時返回值

new內存分配失敗時,會拋出bac_alloc異常,可以使用異常機制來處理;malloc分配內存失敗會返回NULL;所以在c中使用malloc開闢內存都要判斷下返回值類型是否爲空,來確定內存是否開闢成功;

 

五、是否需要指定內存大小

使用new申請內存分配時不需要指定內存塊的大小,編譯器會根據類型信息自行計算;而malloc需要指定所需內存的大小;
 

class A
{
    cout <<"hello";
};
A *p = new A;
A *p = (A*)malloc(sizeof(A));

 

六、是否調用構造函數、析構函數 

使用new操作符來分配對象內存經歷三個階段

1、通過operator new函數(對於數組是operator new[] 函數)分配一塊足夠大的,原始的,未命名的內存空間以便於存儲特定類型的對象
2、編譯器運行相應的構造函數以構造對象,併爲其傳入初值
3、對象構造完成後,返回一個指向該對象的指針

使用delete操作符來釋放對象內存時會經歷兩個階段

1、調用對象的析構函數
2、通過函數operator delete釋放內存 

使用new和delete會調用對象的構造函數/析構函數。而malloc不會。

 

七、new與malloc是否可以相互調用

operator new和operator delete的實現可以基於malloc,free;反過來,malloc和free的實現不可以調用new和delete。下面是編寫operator new/operator delete的一種簡單方式

void* operator new (size_t size)
{
    if(void *p = malloc(size))
    {
        return p;
    }
    else
    throw bad_alloc();
}
void operator delete(void *p)
{
    free(p);
}

 

 八、對數組的處理

C++提供了new[]與delete[]對數組專門的處理;有new[]分配對應就需要delete[]進行釋放,否則只會對數組中的第一個對象進行釋放,會造成內存泄露。

A *ptr = new A[10];//分配十個對象
delete[] ptr;

上面已經說過,malloc需要指定開闢內存的大小,它並不知道這塊內存上存放的是否是數組,反正就是給你一塊內存並且返回一個內存地址;所以如果要動態分配一個數組的內存,還需要我們手動自定數組的大小;

int *ptr = (int *)malloc(sizeof(int)*10);

 

九、是否可以被重載

operator new/operator delete可以被重載。標準庫是定義了operator new函數和operator delete函數的8個重載版本

//這些版本可能拋出異常
void * operator new(size_t);
void * operator new[](size_t);
void * operator delete (void * )noexcept;
void * operator delete[](void *0)noexcept;
//這些版本承諾不拋出異常
void * operator new(size_t ,nothrow_t&) noexcept;
void * operator new[](size_t, nothrow_t& );
void * operator delete (void *,nothrow_t& )noexcept;
void * operator delete[](void *0,nothrow_t& )noexcept;

而malloc/free不允許重載

 

十、能夠直觀地重新分配內存

使用malloc分配的內存後,如果在使用過程發現內存不足,可以使用realloc函數進行內存重新分配實現內存的擴容;realloc首先判斷當前的指針所指內存是否有足夠的連續空間,如果有,原地擴大可分配的內存地址,並且返回原來的地址指針;如果空間不夠,先按照新指定的大小分配空間,將原來有的數據從頭到尾拷貝到新分配的內存區域,而後釋放原來的內存區域。

new沒有這樣直觀的配套設施來擴充內存。 

 

 

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