日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

C++ new/delete、malloc/free

發(fā)布時(shí)間:2025/3/19 c/c++ 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C++ new/delete、malloc/free 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

2019獨(dú)角獸企業(yè)重金招聘Python工程師標(biāo)準(zhǔn)>>>

http://www.cnblogs.com/growup/archive/2011/06/27/2091101.html

http://blog.csdn.net/passion_wu128/article/details/38966581

new和delete最終調(diào)用malloc和free

1.malloc與free是C++/C語言的標(biāo)準(zhǔn)庫函數(shù),new/delete是C++的運(yùn)算符。它們都可用于申請(qǐng)動(dòng)態(tài)內(nèi)存和釋放內(nèi)存

2.對(duì)于非內(nèi)部數(shù)據(jù)類型的對(duì)象而言,光用maloc/free無法滿足動(dòng)態(tài)對(duì)象的要求。對(duì)象在創(chuàng)建的同時(shí)要自動(dòng)執(zhí)行構(gòu)造函數(shù),對(duì)象在消亡之前要自動(dòng)執(zhí)行析構(gòu)函數(shù)。由malloc/free是庫函數(shù)而不是運(yùn)算符,不在編譯器控制權(quán)限之內(nèi),不能夠把執(zhí)行構(gòu)造函數(shù)和析構(gòu)函數(shù)的任務(wù)強(qiáng)加于malloc/free。

3.因此C++語言需要一個(gè)能完成動(dòng)態(tài)內(nèi)存分配和初始化工作的運(yùn)算符new,以一個(gè)能完成清理與釋放內(nèi)存工作的運(yùn)算符delete。注意new/delete不是庫函數(shù)。?
4.C++程序經(jīng)常要調(diào)用C函數(shù),而C程序只能用malloc/free管理動(dòng)態(tài)內(nèi)存。?
5.new可以認(rèn)為是malloc加構(gòu)造函數(shù)的執(zhí)行。new出來的指針是直接帶類型信息的。而malloc返回的都是void*指針。

new delete在實(shí)現(xiàn)上其實(shí)調(diào)用了malloc,free函數(shù)

6.new建立的對(duì)象你可以把它當(dāng)成一個(gè)普通的對(duì)象,用成員函數(shù)訪問,不要直接訪問它的地址空間;malloc分配的是一塊內(nèi)存區(qū)域,就用指針訪問好了,而且還可以在里面移動(dòng)指針.

7.new 建立的是一個(gè)對(duì)象;alloc分配的是一塊內(nèi)存.

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

相同點(diǎn):都可用于申請(qǐng)動(dòng)態(tài)內(nèi)存和釋放內(nèi)存

不同點(diǎn):?
(1)操作對(duì)象有所不同。?
malloc與free是C++/C 語言的標(biāo)準(zhǔn)庫函數(shù),new/delete 是C++的運(yùn)算符。對(duì)于非內(nèi)部數(shù)據(jù)類的對(duì)象而言,光用maloc/free 無法滿足動(dòng)態(tài)對(duì)象的要求。對(duì)象在創(chuàng)建的同時(shí)要自動(dòng)執(zhí)行構(gòu)造函數(shù), 對(duì)象消亡之前要自動(dòng)執(zhí)行析構(gòu)函數(shù)。由于malloc/free 是庫函數(shù)而不是運(yùn)算符,不在編譯器控制權(quán)限之內(nèi),不能夠把執(zhí)行構(gòu)造函數(shù)和析構(gòu)函數(shù)的任務(wù)強(qiáng)加malloc/free。

(2)在用法上也有所不同。?
函數(shù)malloc 的原型如下:?
void * malloc(size_t size);?
用malloc 申請(qǐng)一塊長(zhǎng)度為length 的整數(shù)類型的內(nèi)存,程序如下:?
int *p = (int *) malloc(sizeof(int) * length);?
我們應(yīng)當(dāng)把注意力集中在兩個(gè)要素上:“類型轉(zhuǎn)換”和“sizeof”。?
malloc 返回值的類型是void *,所以在調(diào)用malloc 時(shí)要顯式地進(jìn)行類型轉(zhuǎn)換,將void * 轉(zhuǎn)換成所需要的指針類型。?
malloc 函數(shù)本身并不識(shí)別要申請(qǐng)的內(nèi)存是什么類型,它只關(guān)心內(nèi)存的總字節(jié)數(shù)。

函數(shù)free 的原型如下:?
void free( void * memblock );?
為什么free 函數(shù)不象malloc 函數(shù)那樣復(fù)雜呢?這是因?yàn)橹羔榩 的類型以及它所指的內(nèi)存的容量事先都是知道的,語句free(p)能正確地釋放內(nèi)存。如果p 是NULL 指針,那么free

對(duì)p 無論操作多少次都不會(huì)出問題。如果p 不是NULL 指針,那么free 對(duì)p連續(xù)操作兩次就會(huì)導(dǎo)致程序運(yùn)行錯(cuò)誤。

new/delete 的使用要點(diǎn)?
運(yùn)算符new 使用起來要比函數(shù)malloc 簡(jiǎn)單得多,例如:?
int *p1 = (int *)malloc(sizeof(int) * length);?
int *p2 = new int[length];?
這是因?yàn)閚ew 內(nèi)置了sizeof、類型轉(zhuǎn)換和類型安全檢查功能。對(duì)于非內(nèi)部數(shù)據(jù)類型的對(duì)象而言,new 在創(chuàng)建動(dòng)態(tài)對(duì)象的同時(shí)完成了初始化工作。如果對(duì)象有多個(gè)構(gòu)造函數(shù),那么new 的語句也可以有多種形式。

如果用new 創(chuàng)建對(duì)象數(shù)組,那么只能使用對(duì)象的無參數(shù)構(gòu)造函數(shù)。例如?
Obj *objects = new Obj[100]; // 創(chuàng)建100 個(gè)動(dòng)態(tài)對(duì)象?
不能寫成?
Obj *objects = new Obj[100](1);// 創(chuàng)建100 個(gè)動(dòng)態(tài)對(duì)象的同時(shí)賦初值1?
在用delete 釋放對(duì)象數(shù)組時(shí),留意不要丟了符號(hào)‘[]’。例如?
delete []objects; // 正確的用法?
delete objects; // 錯(cuò)誤的用法?
后者相當(dāng)于delete objects[0],漏掉了另外99 個(gè)對(duì)象。

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

1? new自動(dòng)計(jì)算需要分配的空間,而malloc需要手工計(jì)算字節(jié)數(shù)?
2? new是類型安全的,而malloc不是,比如:?
int* p = new float[2]; // 編譯時(shí)指出錯(cuò)誤?
int* p = malloc(2*sizeof(float)); // 編譯時(shí)無法指出錯(cuò)誤?
new operator 由兩步構(gòu)成,分別是 operator new 和 construct?
3? operator new對(duì)應(yīng)于malloc,但operator new可以重載,可以自定義內(nèi)存分配策略,甚至不做內(nèi)存分配,甚至分配到非內(nèi)存設(shè)備上。而malloc無能為力?
4? new將調(diào)用constructor,而malloc不能;delete將調(diào)用destructor,而free不能。?
5? malloc/free要庫文件支持,new/delete則不要。

=============================================================

new

new操作針對(duì)數(shù)據(jù)類型的處理,分為兩種情況:

1,簡(jiǎn)單數(shù)據(jù)類型(包括基本數(shù)據(jù)類型和不需要構(gòu)造函數(shù)的類型

代碼實(shí)例:

int*?p?=?new?int;

匯編碼如下:

int*?p?=?new?int; 00E54C44??push????????4?? 00E54C46??call????????operator?new?(0E51384h)?? 00E54C4B??add?????????esp,4

分析:傳入4byte的參數(shù)后調(diào)用operator new。其源碼如下:

void?*__CRTDECL?operator?new(size_t?size)?_THROW1(_STD?bad_alloc){???????//?try?to?allocate?size?bytesvoid?*p;while?((p?=?malloc(size))?==?0)if?(_callnewh(size)?==?0){???????//?report?no?memory_THROW_NCEE(_XSTD?bad_alloc,?);}return?(p);}

分析:調(diào)用malloc失敗后會(huì)調(diào)用_callnewh。如果_callnewh返回0則拋出bac_alloc異常,返回非零則繼續(xù)分配內(nèi)存。

這個(gè)_callnewh是什么呢?它是一個(gè)new handler,通俗來講就是new失敗的時(shí)候調(diào)用的回調(diào)函數(shù)。可以通過_set_new_handler來設(shè)置。下面舉個(gè)實(shí)例:

#include?<stdio.h> #include?<new.h> int?MyNewHandler(size_t?size) {printf("Allocation?failed.Try?again");return?1; //continue?to?allocate//return?0; //stop?allocating,throw?bad_alloc } void?main() {//?Set?the?failure?handler?for?new?to?be?MyNewHandler._set_new_handler(MyNewHandler);while?(1){int*?p?=?new?int[10000000];} }


在new基本數(shù)據(jù)類型的時(shí)候還可以指定初始化值,比如:

int*?p?=?new?int(4);


總結(jié):

  • 簡(jiǎn)單類型直接調(diào)用operator new分配內(nèi)存;

  • 可以通過new_handler來處理new失敗的情況;

  • new分配失敗的時(shí)候不像malloc那樣返回NULL,它直接拋出異常。要判斷是否分配成功應(yīng)該用異常捕獲的機(jī)制;


2,復(fù)雜數(shù)據(jù)類型(需要由構(gòu)造函數(shù)初始化對(duì)象)


代碼實(shí)例:

class?Object { public:Object(){_val?=?1;}~Object(){} private:int?_val; };void?main() {Object*?p?=?new?Object(); }

匯編碼如下:

Object*?p?=?new?Object(); 00AD7EDD??push????????4?? 00AD7EDF??call????????operator?new?(0AD1384h)?? 00AD7EE4??add?????????esp,4?? 00AD7EE7??mov?????????dword?ptr?[ebp-0E0h],eax?? 00AD7EED??mov?????????dword?ptr?[ebp-4],0?? 00AD7EF4??cmp?????????dword?ptr?[ebp-0E0h],0?? 00AD7EFB??je??????????main+70h?(0AD7F10h)?? 00AD7EFD??mov?????????ecx,dword?ptr?[ebp-0E0h]?? 00AD7F03??call????????Object::Object?(0AD1433h)????????//在new的地址上調(diào)用構(gòu)造函數(shù) 00AD7F08??mov?????????dword?ptr?[ebp-0F4h],eax?? 00AD7F0E??jmp?????????main+7Ah?(0AD7F1Ah)?? 00AD7F10??mov?????????dword?ptr?[ebp-0F4h],0?? 00AD7F1A??mov?????????eax,dword?ptr?[ebp-0F4h]?? 00AD7F20??mov?????????dword?ptr?[ebp-0ECh],eax?? 00AD7F26??mov?????????dword?ptr?[ebp-4],0FFFFFFFFh?? 00AD7F2D??mov?????????ecx,dword?ptr?[ebp-0ECh]?? 00AD7F33??mov?????????dword?ptr?[p],ecx

總結(jié):

new 復(fù)雜數(shù)據(jù)類型的時(shí)候先調(diào)用operator new,然后在分配的內(nèi)存上調(diào)用構(gòu)造函數(shù)。

delete

delete也分為兩種情況:

1,簡(jiǎn)單數(shù)據(jù)類型(包括基本數(shù)據(jù)類型和不需要析構(gòu)函數(shù)的類型)。

int?*p?=?new?int(1); delete?p;

delete的匯編碼如下:

delete?p; 00275314??mov?????????eax,dword?ptr?[p]?? 00275317??mov?????????dword?ptr?[ebp-0D4h],eax?? 0027531D??mov?????????ecx,dword?ptr?[ebp-0D4h]?? 00275323??push????????ecx?? 00275324??call????????operator?delete?(0271127h)

分析:傳入?yún)?shù)p之后調(diào)用operator delete,其源碼如下:

void?operator?delete(?void?*?p?) {RTCCALLBACK(_RTC_Free_hook,?(p,?0));free(?p?); }

RTCCALLBACK默認(rèn)是空的宏定義,所以這個(gè)函數(shù)默認(rèn)情況下就是簡(jiǎn)單的調(diào)用free函數(shù)。

總結(jié):

delete簡(jiǎn)單數(shù)據(jù)類型默認(rèn)只是調(diào)用free函數(shù)。


2,復(fù)雜數(shù)據(jù)類型(需要由析構(gòu)函數(shù)銷毀對(duì)象)

代碼實(shí)例:

class?Object { public:Object(){_val?=?1;}~Object(){cout?<<?"destroy?object"?<<?endl;} private:int?_val; };void?main() {Object*?p?=?new?Object;delete?p; }

部分匯編碼如下:

012241F0??mov?????????dword?ptr?[this],ecx?? 012241F3??mov?????????ecx,dword?ptr?[this]?? 012241F6??call????????Object::~Object?(0122111Dh)??????????????????????????//先調(diào)用析構(gòu)函數(shù) 012241FB??mov?????????eax,dword?ptr?[ebp+8]?? 012241FE??and?????????eax,1?? 01224201??je??????????Object::`scalar?deleting?destructor'+3Fh?(0122420Fh)?? 01224203??mov?????????eax,dword?ptr?[this]?? 01224206??push????????eax?? 01224207??call????????operator?delete?(01221145h)?? 0122420C??add?????????esp,4

總結(jié):

delete復(fù)雜數(shù)據(jù)類型先調(diào)用析構(gòu)函數(shù)再調(diào)用operator delete。

new數(shù)組

new[]也分為兩種情況:

1,簡(jiǎn)單數(shù)據(jù)類型(包括基本數(shù)據(jù)類型和不需要析構(gòu)函數(shù)的類型)。

new[] 調(diào)用的是operator new[],計(jì)算出數(shù)組總大小之后調(diào)用operator new。

值得一提的是,可以通過()初始化數(shù)組為零值,實(shí)例:

char*?p?=?new?char[32]();

等同于:

char?*p?=?new?char[32]; memset(p,?32,?0);

總結(jié):

針對(duì)簡(jiǎn)單類型,new[]計(jì)算好大小后調(diào)用operator new。


2,復(fù)雜數(shù)據(jù)類型(需要由析構(gòu)函數(shù)銷毀對(duì)象)

實(shí)例:

class?Object { public:Object(){_val?=?1;}~Object(){cout?<<?"destroy?object"?<<?endl;} private:int?_val; };void?main() {Object*?p?=?new?Object[3]; }

new[]先調(diào)用operator new[]分配內(nèi)存,然后在p的前四個(gè)字節(jié)寫入數(shù)組大小,最后調(diào)用三次構(gòu)造函數(shù)。

實(shí)際分配的內(nèi)存塊如下:


這里為什么要寫入數(shù)組大小呢?因?yàn)閷?duì)象析構(gòu)時(shí)不得不用這個(gè)值,舉個(gè)例子:

class?Object { public:Object(){_val?=?1;}virtual?~Object(){cout?<<?"destroy?Object"?<<?endl;} private:int?_val; };class?MyObject?:?public?Object { public:~MyObject(){cout?<<?"destroy?MyObject"?<<?endl;} private:int?_foo; };void?main() {Object*?p?=?new?MyObject[3];delete[]?p; }

釋放內(nèi)存之前會(huì)調(diào)用每個(gè)對(duì)象的析構(gòu)函數(shù)。但是編譯器并不知道p實(shí)際所指對(duì)象的大小。如果沒有儲(chǔ)存數(shù)組大小,編譯器如何知道該把p所指的內(nèi)存分為幾次來調(diào)用析構(gòu)函數(shù)呢?

總結(jié):

針對(duì)復(fù)雜類型,new[]會(huì)額外存儲(chǔ)數(shù)組大小。

delete數(shù)組

delete[]也分為兩種情況:

1,簡(jiǎn)單數(shù)據(jù)類型(包括基本數(shù)據(jù)類型和不需要析構(gòu)函數(shù)的類型)。

delete和delete[]效果一樣

比如下面的代碼:

int*?pint?=?new?int[32]; delete?pint;char*?pch?=?new?char[32]; delete?pch;

運(yùn)行后不會(huì)有什么問題,內(nèi)存也能完成的被釋放。看下匯編碼就知道operator delete[]就是簡(jiǎn)單的調(diào)用operator delete。

總結(jié):

針對(duì)簡(jiǎn)單類型,delete和delete[]等同。


2,復(fù)雜數(shù)據(jù)類型(需要由析構(gòu)函數(shù)銷毀對(duì)象)

釋放內(nèi)存之前會(huì)先調(diào)用每個(gè)對(duì)象的析構(gòu)函數(shù)。

new[]分配的內(nèi)存只能由delete[]釋放。如果由delete釋放會(huì)崩潰,為什么會(huì)崩潰呢?

假設(shè)指針p指向new[]分配的內(nèi)存。因?yàn)橐?字節(jié)存儲(chǔ)數(shù)組大小,實(shí)際分配的內(nèi)存地址為[p-4],系統(tǒng)記錄的也是這個(gè)地址。delete[]實(shí)際釋放的就是p-4指向的內(nèi)存。而delete會(huì)直接釋放p指向的內(nèi)存,這個(gè)內(nèi)存根本沒有被系統(tǒng)記錄,所以會(huì)崩潰。

總結(jié):

針對(duì)復(fù)雜類型,new[]出來的內(nèi)存只能由delete[]釋放。

轉(zhuǎn)載于:https://my.oschina.net/u/223340/blog/547018

與50位技術(shù)專家面對(duì)面20年技術(shù)見證,附贈(zèng)技術(shù)全景圖

總結(jié)

以上是生活随笔為你收集整理的C++ new/delete、malloc/free的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。