new malloc
https://blog.csdn.net/happyxieqiang/article/details/50775847
?
0.?????? 屬性
new/delete是C++關(guān)鍵字,需要編譯器支持。malloc/free是庫(kù)函數(shù),需要頭文件支持。
1.?????? 參數(shù)
使用new操作符申請(qǐng)內(nèi)存分配時(shí)無須指定內(nèi)存塊的大小,編譯器會(huì)根據(jù)類型信息自行計(jì)算。而malloc則需要顯式地指出所需內(nèi)存的尺寸。
2.?????? 返回類型
new操作符內(nèi)存分配成功時(shí),返回的是對(duì)象類型的指針,類型嚴(yán)格與對(duì)象匹配,無須進(jìn)行類型轉(zhuǎn)換,故new是符合類型安全性的操作符。而malloc內(nèi)存分配成功則是返回void * ,需要通過強(qiáng)制類型轉(zhuǎn)換將void*指針轉(zhuǎn)換成我們需要的類型。
3.?????? 分配失敗
new內(nèi)存分配失敗時(shí),會(huì)拋出bac_alloc異常。malloc分配內(nèi)存失敗時(shí)返回NULL。
4.??????自定義類型
???????? new會(huì)先調(diào)用operator new函數(shù),申請(qǐng)足夠的內(nèi)存(通常底層使用malloc實(shí)現(xiàn))。然后調(diào)用類型的構(gòu)造函數(shù),初始化成員變量,最后返回自定義類型指針。delete先調(diào)用析構(gòu)函數(shù),然后調(diào)用operator delete函數(shù)釋放內(nèi)存(通常底層使用free實(shí)現(xiàn))。
???????? malloc/free是庫(kù)函數(shù),只能動(dòng)態(tài)的申請(qǐng)和釋放內(nèi)存,無法強(qiáng)制要求其做自定義類型對(duì)象構(gòu)造和析構(gòu)工作。
5.??????重載
C++允許重載new/delete操作符,特別的,布局new的就不需要為對(duì)象分配內(nèi)存,而是指定了一個(gè)地址作為內(nèi)存起始區(qū)域,new在這段內(nèi)存上為對(duì)象調(diào)用構(gòu)造函數(shù)完成初始化工作,并返回此地址。而malloc不允許重載。
6.?????? 內(nèi)存區(qū)域
new操作符從自由存儲(chǔ)區(qū)(free store)上為對(duì)象動(dòng)態(tài)分配內(nèi)存空間,而malloc函數(shù)從堆上動(dòng)態(tài)分配內(nèi)存。自由存儲(chǔ)區(qū)是C++基于new操作符的一個(gè)抽象概念,凡是通過new操作符進(jìn)行內(nèi)存申請(qǐng),該內(nèi)存即為自由存儲(chǔ)區(qū)。而堆是操作系統(tǒng)中的術(shù)語,是操作系統(tǒng)所維護(hù)的一塊特殊內(nèi)存,用于程序的內(nèi)存動(dòng)態(tài)分配,C語言使用malloc從堆上分配內(nèi)存,使用free釋放已分配的對(duì)應(yīng)內(nèi)存。自由存儲(chǔ)區(qū)不等于堆,如上所述,布局new就可以不位于堆中。
?
?
今天偶然看到一個(gè)面試經(jīng)驗(yàn)中提到malloc和new的區(qū)別,突然發(fā)現(xiàn)自己雖然兩個(gè)都用過,但是至于區(qū)別,真的不是很明白 ,所以就仔細(xì)查了一些資料,算是對(duì)這個(gè)點(diǎn)徹底地了解一下,現(xiàn)在把我所學(xué)到的記錄下來。
malloc與free是C++/C語言的標(biāo)準(zhǔn)庫(kù)函數(shù),new/delete是C++的運(yùn)算符。它們都可用于申請(qǐng)動(dòng)態(tài)內(nèi)存和釋放內(nèi)存。
1.malloc函數(shù)初探
首先我們要知道m(xù)alloc是一個(gè)函數(shù),malloc的全稱是memory allocation,中文叫動(dòng)態(tài)內(nèi)存分配。它的原型是:
void *malloc(int size);- 1
說明:malloc 向系統(tǒng)申請(qǐng)分配指定size個(gè)字節(jié)的內(nèi)存空間,返回類型是 void* 類型。void* 表示未確定類型的指針。C,C++規(guī)定,void* 類型可以強(qiáng)制轉(zhuǎn)換為任何其它類型的指針。 ?
在這里注意:?
(1) void* 表示未確定類型的指針,更明確的說是指申請(qǐng)內(nèi)存空間時(shí)還不知道用戶是用這段空間來存儲(chǔ)什么類型的數(shù)據(jù)(比如是char還是int或者…)?
(2) 使用malloc向系統(tǒng)申請(qǐng)內(nèi)存時(shí)可能分配失敗。如果分配失敗,則返回一個(gè)空指針(NULL)。關(guān)于分配失敗的原因,有很多種,比如說空間不足就是一種。?
一個(gè)對(duì)應(yīng)的釋放內(nèi)存的函數(shù):
- 1
該函數(shù)是將之前用malloc分配的空間還給程序或者是操作系統(tǒng),也就是釋放了這塊內(nèi)存,讓它重新得到自由。?
至于用法,其實(shí)這兩個(gè)函數(shù)用起來倒不是很難,也就是malloc()之后覺得不用了需要釋放把它給free()了,舉個(gè)簡(jiǎn)單例子:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
當(dāng)然,具體情況要具體分析以及具體解決。比如說,你定義了一個(gè)指針,在一個(gè)函數(shù)里申請(qǐng)了一塊內(nèi)存然后通過函數(shù)返回傳遞給這個(gè)指針,那么也許釋放這塊內(nèi)存這項(xiàng)工作就應(yīng)該留給其他函數(shù)了。只要保證每個(gè)malloc()之后必須有一個(gè)free()與之對(duì)應(yīng)。
關(guān)于這個(gè)函數(shù)的用法需要注意的一些地方:
1.申請(qǐng)了內(nèi)存空間后,必須檢查是否分配成功。
2.當(dāng)不需要再使用申請(qǐng)的內(nèi)存時(shí),記得釋放;釋放后應(yīng)該把指向這塊內(nèi)存的指針指向NULL,防止程序后面不小心使用了它。
3.這兩個(gè)函數(shù)應(yīng)該是配對(duì)。如果申請(qǐng)后不釋放就是內(nèi)存泄露;如果無故釋放那就是什么也沒有做。釋放只能一次,如果釋放兩次及兩次以上會(huì)出現(xiàn)錯(cuò)誤(釋放空指針例外,釋放空指針其實(shí)也等于啥也沒做,所以釋放空指針釋放多少次都沒有問題)。
4.雖然malloc()函數(shù)的類型是void*,任何類型的指針都可以轉(zhuǎn)換成void*,但是最好還是在前面進(jìn)行強(qiáng)制類型轉(zhuǎn)換,因?yàn)檫@樣可以躲過一些編譯器的檢查。
2.malloc函數(shù)深入
看了以上的內(nèi)容我們大致知道m(xù)alloc函數(shù)的初步內(nèi)容以及它的用法,但是我們不知道m(xù)alloc函數(shù)是怎么實(shí)現(xiàn)動(dòng)態(tài)分配內(nèi)存的。那它是怎么動(dòng)態(tài)分配內(nèi)存的呢?
答案是從堆里面獲得空間。也就是說函數(shù)返回的指針是指向堆里面的一塊內(nèi)存。操作系統(tǒng)中有一個(gè)記錄空閑內(nèi)存地址的鏈表。當(dāng)操作系統(tǒng)收到程序的申請(qǐng)時(shí),就會(huì)遍歷該鏈表,然后就尋找第一個(gè)空間大于所申請(qǐng)空間的堆結(jié)點(diǎn),然后就將該結(jié)點(diǎn)從空閑結(jié)點(diǎn)鏈表中刪除,并將該結(jié)點(diǎn)的空間分配給程序。
說到這里就不得不提堆,什么是堆呢?堆是大家共有的空間,分全局堆和局部堆。全局堆就是所有沒有分配的空間,局部堆就是用戶分配的空間。堆在操作系統(tǒng)對(duì)進(jìn)程 初始化的時(shí)候分配,運(yùn)行過程中也可以向系統(tǒng)要額外的堆,記住一點(diǎn):從堆申請(qǐng)的內(nèi)存用完了要還給操作系統(tǒng),也就是釋放,如果不還的話會(huì)發(fā)生內(nèi)存泄露。
而所謂內(nèi)存泄露就好比你去食堂吃飯,你吃完了之后沒把盤子拿走,這在別人看來是這個(gè)座有人占了,可怕的是你回頭吃飯又占了一個(gè)新座,你吃完之后還是沒把盤子拿走……終于,整個(gè)食堂的座位都被占滿了,食堂也亂套了。(比喻不太恰當(dāng),但大致是這個(gè)意思)
平常我們老說堆棧、堆棧,那棧又是什么呢?棧是線程獨(dú)有的,保存其運(yùn)行狀態(tài)和局部自動(dòng)變量的。棧在線程開始的時(shí)候初始化,每個(gè)線程的?;ハ嗒?dú)立。每個(gè)函數(shù)都有自己的棧,棧被用來在函數(shù)之間傳遞參數(shù)。操作系統(tǒng)在切換線程的時(shí)候會(huì)自動(dòng)的切換棧,就是切換SS/ESP寄存器。??臻g不需要在高級(jí)語言里面顯式的分配和釋放。
通過上面對(duì)概念的描述,可以知道:
棧是由編譯器自動(dòng)分配釋放,存放函數(shù)的參數(shù)值、局部變量的值等。操作方式類似于數(shù)據(jù)結(jié)構(gòu)中的棧。
堆一般由程序員分配釋放,若不釋放,程序結(jié)束時(shí)可能由操作系統(tǒng)回收。注意這里說是可能,并非一定。所以堆一定要釋放!
3.new運(yùn)算符
3.1 C++中,用new和delete動(dòng)態(tài)創(chuàng)建和釋放數(shù)組或單個(gè)對(duì)象。?
動(dòng)態(tài)創(chuàng)建對(duì)象時(shí),只需指定其數(shù)據(jù)類型,而不必為該對(duì)象命名,new表達(dá)式返回指向該新創(chuàng)建對(duì)象的指針,我們可以通過指針來訪問此對(duì)象。
- 1
這個(gè)new表達(dá)式在堆區(qū)中分配創(chuàng)建了一個(gè)整型對(duì)象,并返回此對(duì)象的地址,并用該地址初始化指針pi 。
3.2 動(dòng)態(tài)創(chuàng)建對(duì)象的初始化
動(dòng)態(tài)創(chuàng)建的對(duì)象可以用初始化變量的方式初始化。
int *pi=new int(100); //指針pi所指向的對(duì)象初始化為100 string *ps=new string(10,'9');//*ps 為“9999999999”- 1
- 2
如果不提供顯示初始化,對(duì)于類類型,用該類的默認(rèn)構(gòu)造函數(shù)初始化;而內(nèi)置類型的對(duì)象則無初始化。?
也可以對(duì)動(dòng)態(tài)創(chuàng)建的對(duì)象做值初始化:
- 1
- 2
- 3
3.3 撤銷動(dòng)態(tài)創(chuàng)建的對(duì)象?
delete表達(dá)式釋放指針指向的地址空間。
- 1
- 2
如果指針指向的不是new分配的內(nèi)存地址,則使用delete是不合法的。
3.4 在delete之后,重設(shè)指針的值
delete p;- 1
執(zhí)行完該語句后,p變成了不確定的指針,在很多機(jī)器上,盡管p值沒有明確定義,但仍然存放了它之前所指對(duì)象的地址,然后p所指向的內(nèi)存已經(jīng)被釋放了,所以p不再有效。此時(shí),該指針變成了懸垂指針(懸垂指針指向曾經(jīng)存放對(duì)象的內(nèi)存,但該對(duì)象已經(jīng)不存在了)。懸垂指針往往導(dǎo)致程序錯(cuò)誤,而且很難檢測(cè)出來。?
一旦刪除了指針?biāo)傅膶?duì)象,立即將指針置為0,這樣就非常清楚的指明指針不再指向任何對(duì)象。(零值指針:int *ip=0;)
3.5 區(qū)分零值指針和NULL指針
零值指針,是值是0的指針,可以是任何一種指針類型,可以是通用變體類型void*也可以是char*,int*等等。?
空指針,其實(shí)空指針只是一種編程概念,就如一個(gè)容器可能有空和非空兩種基本狀態(tài),而在非空時(shí)可能里面存儲(chǔ)了一個(gè)數(shù)值是0,因此空指針是人為認(rèn)為的指針不提供任何地址訊息。
4.malloc和new的區(qū)別
(1)?new 返回指定類型的指針,并且可以自動(dòng)計(jì)算所需要大小。而 malloc 則必須要由我們計(jì)算字節(jié)數(shù),并且在返回后強(qiáng)行轉(zhuǎn)換為實(shí)際類型的指針。?
例:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
(2)?malloc 只管分配內(nèi)存,并不能對(duì)所得的內(nèi)存進(jìn)行初始化,所以得到的一片新內(nèi)存中,其值將是隨機(jī)的。new創(chuàng)建的對(duì)象可以用初始化變量的方式初始化。
除了分配及最后釋放的方法不一樣以外,通過malloc或new得到指針,在其它操作上保持一致。
轉(zhuǎn)載于:https://www.cnblogs.com/diegodu/p/9190717.html
總結(jié)
以上是生活随笔為你收集整理的new malloc的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 期货大赛项目|九,fileinput插件
- 下一篇: plsqldevelop安装教程