C++ 中 malloc/free與 new/delete區別


new/delete 通常來說是操作符,就是"+","-"一樣,malloc/free 是 C++/C 語言的標准庫函數 —— 本質區別。本文主要從以下5各方面比較、分析 malloc/free,new/delete 的區別 。 1.自動地分配所需空間。2.自動返回指針類型。3.初始化不同。4.源碼實現不同。5.常見問題為什么有了new不剔除malloc。
【正文】
本質區別
new/delete 通常來說是操作符,就是"+","-"一樣。 malloc/free 是 C++/C 語言的標准庫函數 ——本質區別;
操作對象范圍不同

new/delete 是 C++ 里才有的,而 new/delete 與 malloc/free 一個顯著的區別在於,new 是建造一個對象,並調用對象的構造函數來初始化對象,其實在所有的 new 操作過程中,總是分為兩步的:第一步是申請內存,第二步則是調用構造函數初始化對象(也有文章指出,第三步是返回指針所指向對象的類型和地址)。同樣,在調用 delete 的時候,需要先調用析構函數,然后在銷毀堆內存。換言之 , 對於非內部數據類型的對象而言,光用 malloc/free 無法滿足動態對象的要求。對象在創建的同時要自動執行構造函數,對象在消亡之前要自動執行析構函數。由於 malloc/free 是庫函數而不是運算符,不在編譯器控制權限之內,不能夠把執行構造函數和析構函數的任務強加於 malloc/free 。如果用 free 釋放“ new 創建的動態對象”,那么該對象因無法執行析構函數而可能導致程序出錯。如果用 delete 釋放“ malloc 申請的動態內存”,理論上講程序不會出錯,但是該程序的可讀性很差。所以 new/delete 必須配對使用, malloc/free 也一樣。 C++ 默認的 new/delete 操作符內部,其實也調用了 malloc/free 這兩個函數;


使用方法上的區別

1. new能夠按照變量類型自動地分配所需空間長度,不必使用宏sizeof。

2. new能夠自動返回正確的指針類型。

3. 必須時,new能將單個變量初始化。

用例闡述


malloc
用 malloc 申請一塊長度為length 的整數類型的內存,程序如下:
int *p = (int *) malloc ( sizeof(int) * length);
我們應當把注意力集中在兩個要素上:“類型轉換”和“sizeof”。
void * malloc(size_t size);
1、malloc 返回值的類型是 void *,所以在調用 malloc 時要顯式地進行類型轉換,將 void * 轉換成所需要的指針類型。
2、malloc 函數本身並不識別要申請的內存是什么類型,它只關心內存的總字節數。


free
void free( void * memblock );
為什么free 函數不象malloc 函數那樣復雜呢?這是因為指針p 的類型以及它所指的內存的容量事先都是知道的,語句free(p)能正確地釋放內存。如果p 是NULL 指針,那么free對p 無論操作多少次都不會出問題。如果p 不是NULL 指針,那么free 對p連續操作兩次就會導致程序運行錯誤。(懸浮指針和空指針的區別就在這里)

new/delete
運算符 new 使用起來要比函數 malloc 簡單得多,例如:
int *p1 = (int *)malloc(sizeof(int) * length);
int *p2 = new int[length];
這是因為 new 內置了sizeof、類型轉換和類型安全檢查功能。對於非內部數據類型的對象而言,new 在創建動態對象的同時完成了初始化工作。如果對象有多個構造函數,那么new 的語句也可以有多種形式。
如果用new 創建對象數組,那么只能使用對象的無參數構造函數。例如
Obj *objects = new Obj[100]; // 創建100 個動態對象
不能寫成
Obj *objects = new Obj[100](1);// 創建100 個動態對象的同時賦初值1
在用delete 釋放對象數組時,留意不要丟了符號‘[ ]’。例如
delete []objects; // 正確的用法
delete objects; // 錯誤的用法
后者相當於delete objects[0],漏掉了另外99 個對象。
malloc/free 與 new/delete共同點
1 都必須配對使用,這里的配對使用,可不能理解為一個 new/malloc 就對應一個 delete/free ,而是指在作用域內,new/malloc 所申請的內存,必須被有效釋放,否則將會導致內存泄露,至於內存泄露的檢查方法,我們推薦的工具是大家眾所周知的 Bounds Checker;

2 都是申請內存,釋放內存,free和delete可以釋放NULL指針。
既然new/delete的功能完全覆蓋了malloc /free,為什么C++還保留malloc/free呢?
對於非內部數據類型對象(如類對象)而言,只用malloc/free 無法滿足動態對象的要求。對象在創建的同時要自動執行構造函數,對象在消亡之前要自動執行析構函數。

由於,malloc/free是庫函數而不是運算符,不在編譯器控制權限之內,也就不能執行構造函數和析構函數,不能夠把執行構造函數和析構函數的任務強加於malloc/free。

所以,若要強求使用malloc/free庫函數實現非內部數據類型對象的內存管理,在malloc()后要有一個類對象的初始化來承擔構造函數的功能,同時,在free之前也要有一個消除函數來充當析構函數的功能,當然這是很不方便,也是不提倡的。

因此,C++語言需要一個能完成動態內存分配和初始化工作的運算符new,以及一個能完成清理與釋放內存工作的運算符delete。new/delete不是庫函數,而是運算符。

而對於內部數據類型,由於內部數據類型的對象沒有構造函數與析構函數的過程,對他們來說,malloc/free與new/delete是等價的。

或許你會問,既然new/delete的功能完全可以實現malloc/free的功能,為什么C++中不把malloc/free淘汰掉呢,這可能涉及到一個兼容性問題,C++程序要經常調用C函數,而C語言中只能用malloc/free來管理內存。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM