new與malloc的區別

new與malloc的區別

 首先摘錄《effectivec c++》條款3

malloc和free(及其變體)會產生問題的原因在於它們太簡單:他們不知道構造函數和析構函數。

假設用兩種方法給一個包含10個string對象的數組分配空間,一個用malloc,另一個用new:

  

string *stringarray1 =
static_cast<string*>(malloc(10 * sizeof(string)));

string *stringarray2 = new string[10];

其結果是,stringarray1確實指向的是可以容納10個string對象的足夠空間,但內存裏並沒有創建這些對象。而且,如果你不從這種晦澀的語法怪圈(詳見條款m4和m8的描述)裏跳出來的話,你沒有辦法來初始化數組裏的對象。換句話說,stringarray1其實一點用也沒有。相反,stringarray2指向的是一個包含10個完全構造好的string對象的數組,每個對象可以在任何讀取string的操作裏安全使用。

假設你想了個怪招對stringarray1數組裏的對象進行了初始化,那麼在你後面的程序裏你一定會這麼做:

free(stringarray1);
delete [] stringarray2;// 參見條款5:這裏爲什麼要加上個"[]"

調用free將會釋放stringarray1指向的內存,但內存裏的string對象不會調用析構函數。如果string對象象一般情況那樣,自己已經分配了內存,那這些內存將會全部丟失。相反,當對stringarray2調用delete時,數組裏的每個對象都會在內存釋放前調用析構函數。

既然new和delete可以這麼有效地與構造函數和析構函數交互,選用它們是顯然的。

把new和delete與malloc和free混在一起用也是個壞想法。對一個用new獲取來的指針調用free,或者對一個用malloc獲取來的指針調用delete,其後果是不可預測的。大家都知道“不可預測”的意思:它可能在開發階段工作良好,在測試階段工作良好,但也可能會最後在你最重要的客戶的臉上爆炸。

new/delete和malloc/free的不兼容性常常會導致一些嚴重的複雜性問題。舉個例子,<string.h>裏通常有個strdup函數,它得到一個char*字符串然後返回其拷貝:

char * strdup(const char *ps);	// 返回ps所指的拷貝

在有些地方,c和c++用的是同一個strdup版本,所以函數內部是用malloc分配內存。這樣的話,一些不知情的c++程序員會在調用strdup後忽視了必須對strdup返回的指針進行free操作。爲了防止這一情況,有些地方會專門爲c++重寫strdup,並在函數內部調用了new,這就要求其調用者記得最後用delete。你可以想象,這會導致多麼嚴重的移植性問題,因爲代碼中strdup以不同的形式在不同的地方之間顛來倒去。

c++程序員和c程序員一樣對代碼重用十分感興趣。大家都知道,有大量基於malloc和free寫成的代碼構成的c庫都非常值得重用。在利用這些庫時,最好是你不用負責去free掉由庫自己malloc的內存,並且/或者,你不用去malloc庫自己會free掉的內存,這樣就太好了。其實,在c++程序裏使用malloc和free沒有錯,只要保證用malloc得到的指針用free,或者用new得到的指針最後用delete來操作就可以了。千萬別馬虎地把new和free或malloc和delete混起來用,那隻會自找麻煩。

既然malloc和free對構造函數和析構函數一無所知,把malloc/free和new/delete混起來用又象嘈雜擁擠的晚會那樣難以控制,那麼,你最好就什麼時候都一心一意地使用new和delete吧。


最後總結一下區別:

1.malloc與free是C++/C語言的標準庫函數,new/delete是C++的運算符。它們都可用於申請動態內存和釋放內存

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

3.因此C++語言需要一個能完成動態內存分配和初始化工作的運算符new,以一個能完成清理與釋放內存工作的運算符delete。注意new/delete不是庫函數。 
4.C++程序經常要調用C函數,而C程序只能用malloc/free管理動態內存。 
5.new可以認爲是malloc加構造函數的執行。new出來的指針是直接帶類型信息的。而malloc返回的都是void*指針。

new/delete在實現上其實調用了malloc,free函數

6.new建立的對象你可以把它當成一個普通的對象,用成員函數訪問,不要直接訪問它的地址空間;malloc分配的是一塊內存區域,就用指針訪問好了,而且還可以在裏面移動指針.

7.new 建立的是一個對象;malloc分配的是一塊內存.

***************************************

相同點:都可用於申請動態內存和釋放內存

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

(2)在用法上也有所不同。 
函數malloc 的原型如下: 
void * malloc(size_t size); 
用malloc 申請一塊長度爲length 的整數類型的內存,程序如下: 
int *p = (int *) malloc(sizeof(int) * length); 
我們應當把注意力集中在兩個要素上:“類型轉換”和“sizeof”。 
malloc 返回值的類型是void *,所以在調用malloc 時要顯式地進行類型轉換,將void * 轉換成所需要的指針類型。 
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 個對象。

*****************************************************************************************************************

1  new自動計算需要分配的空間,而malloc需要手工計算字節數 
2  new是類型安全的,而malloc不是,比如: 
int* p = new float[2]; // 編譯時指出錯誤 
int* p = malloc(2*sizeof(float)); // 編譯時無法指出錯誤 
new operator 由兩步構成,分別是 operator new 和 construct 
3  operator new對應於malloc,但operator new可以重載,可以自定義內存分配策略,甚至不做內存分配,甚至分配到非內存設備上。而malloc無能爲力 
4  new將調用constructor,而malloc不能;delete將調用destructor,而free不能。 
5  malloc/free要庫文件支持,new/delete則不要

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