new/delete和malloc/free的區別-zz

1、new 是c++中的操作符,malloc是c 中的一個函數

2、new 不止是分配內存,而且會調用類的構造函數,同理delete會調用類的析構函數,而malloc則只分配內存,不會進行初始化類成員的工作,同樣free也不會調用析構函數

3、內存泄漏對於malloc或者new都可以檢查出來的,區別在於new可以指明是那個文件的那一行,而malloc沒有這些信息。

4、new 和 malloc效率比較

new可以認爲是malloc加構造函數的執行。

new出來的指針是直接帶類型信息的。

而malloc返回的都是void指針。

 

一:new delete 是運算符,malloc,free是函數

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

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

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

我們先看一看malloc/free和new/delete如何實現對象的動態內存管理,見示例。


class Obj

{

public :

          Obj(void){ cout << “Initialization” << endl; }

~Obj(void){ cout << “Destroy” << endl; }

void      Initialize(void){ cout << “Initialization” << endl; }

void      Destroy(void){ cout << “Destroy” << endl; }

};


void UseMallocFree(void)

{

      Obj    *a = (obj *)malloc(sizeof(obj));     // 申請動態內存

      a->Initialize();                          // 初始化

      //…

      a->Destroy();     // 清除工作

      free(a);          // 釋放內存

}


void UseNewDelete(void)

{

      Obj    *a = new Obj;    // 申請動態內存並且初始化

      //…

      delete a;             // 清除並且釋放內存

}

示例用malloc/free和new/delete如何實現對象的動態內存管理

類Obj的函數Initialize模擬了構造函數的功能,函數Destroy模擬了析構函數的功能。函數UseMallocFree中,由於malloc/free不能執行構造函數與析構函數,必須調用成員函數Initialize和Destroy來完成初始化與清除工作。函數UseNewDelete則簡單得多。

所以我們不要企圖用malloc/free來完成動態對象的內存管理,應該用new/delete。由於內部數據類型的“對象”沒有構造與析構的過程,對它們而言malloc/free和new/delete是等價的。

既然new/delete的功能完全覆蓋了malloc/free,爲什麼C++不把malloc/free淘汰出局呢?這是因爲C++程序經常要調用C函數,而C程序只能用malloc/free管理動態內存。

如果用free釋放“new創建的動態對象”,那麼該對象因無法執行析構函數而可能導致程序出錯。如果用delete釋放“malloc申請的動態內存”,理論上講程序不會出錯,但是該程序的可讀性很差。所以new/delete必須配對使用,malloc/free也一樣。

 

二:new delete在實現上其實調用了malloc,free函數。

 

三:new operator除了分配內存,還要調用構造函數。malloc函數只是負責分配內存。

 

簡而言之:
new   是一個操作符,可以重載   
malloc是一個函數,可以覆蓋   
new   初始化對象,調用對象的構造函數,對應的delete調用相應的析構函數   
malloc僅僅分配內存,free僅僅回收內存  

 

 

 

 

 

問題:

我又一個對象類,裏面有一個指針鏈表,動態分配空間,在析構的時候釋放。開始對對象進行new操作,但是執行delete對象操作的時候出錯,提示在析構的時候內存有問題。可是這時候成員一個比特的內存都沒有分配啊。所以析構的時候應該什麼內存操作都不執行。
更奇怪的是採用free()函數就可以釋放這種對象,但是內存卻不見減少,整個程序內存佔用節節升高?這是爲什麼?

回覆1:

你在析構函數當中沒有正確的釋放你申請的內存,比如,這個對象當中有一個指針,是採用動態申請內存的,在構造函數當中應該把它的值設置爲NULL,然後在某個方法當中會申請內存,是採用new方法進行申請的,在析構函當中,應該先判斷該指針是否爲空,如果不爲空,則使用delete釋放內存,然後再把該指針設置爲NULL。這樣就可以了,如果你在外面是採用new申請這個對象,則在使用完成後使用delete釋放就可以了。

回覆2:

補充一點:new和malloc雖然都是申請內存,但申請的位置不同,new的內存從free store
分配,而malloc的內存從heap分配(詳情請看ISO14882的內存管理部分),
free store和heap很相似,都是動態內存,但是位置不同,這就是爲什麼new
出來的內存不能通過free來釋放的原因。不過微軟編譯器並沒有很好的執行標準,
很有可能把free store和heap混淆了,因此,free有時也可以。再補充一點:delete時候不需要檢查NULL

回覆3:

呵,我也來湊合
如果TYPE *p = new TYPE[n]  那麼就要 delete[] p

回覆4:

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吧。

回覆5:

malloc與free是C++/C語言的標準庫函數,new/delete是C++的運算符。它們都可用於申請動態內存和釋放內存。
對於非內部數據類型的對象而言,光用maloc/free無法滿足動態對象的要求。對象在創建的同時要自動執行構造函數,對象在消亡之前要自動執行析構函數。由於malloc/free是庫函數而不是運算符,不在編譯器控制權限之內,不能夠把執行構造函數和析構函數的任務強加於malloc/free。因此C++語言需要一個能完成動態內存分配和初始化工作的運算符new,以及一個能完成清理與釋放內存工作的運算符delete。注意new/delete不是庫函數。

回覆6:

delete的時候可能需要釋放多個指針的內存
free和delete的區別是
對於對象來說
free的確釋放了對象的內存,但是不調用對象的析構函數,所以如果在對象中使用new分配的內存就會泄露
delete不僅釋放對象的內存,並且調用對象的析構函數

 

發佈了15 篇原創文章 · 獲贊 1 · 訪問量 24萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章