您好,登錄后才能下訂單哦!
這篇文章主要為大家展示了“C++中動(dòng)態(tài)內(nèi)存管理的示例分析”,內(nèi)容簡(jiǎn)而易懂,條理清晰,希望能夠幫助大家解決疑惑,下面讓小編帶領(lǐng)大家一起研究并學(xué)習(xí)一下“C++中動(dòng)態(tài)內(nèi)存管理的示例分析”這篇文章吧。
計(jì)算機(jī)物理內(nèi)存的大小是固定的,在32位系統(tǒng)上,地址空間可達(dá)4G(2^32),這4G按照3:1的比例分配給用戶(hù)進(jìn)程和內(nèi)核。程序地址空間的構(gòu)成:從上往下依次是:內(nèi)核空間、棧區(qū)、共享區(qū)、堆區(qū)、未初始化數(shù)據(jù)區(qū)、初始化數(shù)據(jù)區(qū)、代碼區(qū)。而動(dòng)態(tài)內(nèi)存管理所申請(qǐng)的空間都是在堆區(qū),在堆區(qū)動(dòng)態(tài)開(kāi)辟的空間都需要我們手動(dòng)去釋放它,否則會(huì)造成內(nèi)存泄漏。
內(nèi)核空間:操作系統(tǒng)相關(guān)代碼
棧區(qū):從高地址向低地址增長(zhǎng)
共享區(qū):加載動(dòng)態(tài)庫(kù),共享內(nèi)存
堆區(qū):從低地址向高地址增長(zhǎng)
未初始化全局?jǐn)?shù)據(jù)區(qū)
已初始化全局?jǐn)?shù)據(jù)區(qū)
代碼區(qū):可執(zhí)行代碼及只讀常量
void* malloc(size_t size);
malloc()函數(shù)只有一個(gè)參數(shù),即要分配的內(nèi)存空間的大小。
如果開(kāi)辟成功,則返回一個(gè)指向開(kāi)辟好空間的指針,如果開(kāi)辟失敗,則返回一個(gè)空指針,因此每次申請(qǐng)完空間都需要判空。
malloc()函數(shù)返回值的類(lèi)型是void*,在使用時(shí)需要自己強(qiáng)制轉(zhuǎn)換。
void* calloc (size_t num, size_t size);
calloc()函數(shù)有兩個(gè)參數(shù),分別是元素的數(shù)目和每個(gè)元素的大小,這兩個(gè)參數(shù)的乘積就是要分配的內(nèi)存空間的大小。
malloc申請(qǐng)后空間的值是隨機(jī)的,并沒(méi)有進(jìn)行初始化,而calloc在申請(qǐng)后,對(duì)空間逐一進(jìn)行初始化,并設(shè)置值為0;
calloc由于給每一個(gè)空間都要初始化,所以效率必然比malloc低。
void* realloc (void* ptr, size_t size);
realloc()函數(shù)就實(shí)現(xiàn)對(duì) 動(dòng)態(tài)開(kāi)辟 內(nèi)存大小的調(diào)整。
realloc()函數(shù)包含兩個(gè)參數(shù),分別是要調(diào)整的內(nèi)存地址和調(diào)整的新大小。
realloc在調(diào)整內(nèi)存空間時(shí)有兩種情況:
情況1:原有空間之后有足夠大的空間,我們就把需要擴(kuò)展的內(nèi)存直接放到原來(lái)空間的后面,原來(lái)空間的數(shù)據(jù)不發(fā)生變化。
情況2:原有空間之后沒(méi)有足夠大的空間,那就在堆上找一個(gè)合適大小的連續(xù)空間,將原來(lái)內(nèi)存中的數(shù)據(jù)移動(dòng)到新空間,然后將這個(gè)新空間的地址返回。
void* free(void* ptr);
free函數(shù)用來(lái)釋放動(dòng)態(tài)開(kāi)辟的函數(shù)。
C++作為一門(mén)在C語(yǔ)言的基礎(chǔ)上發(fā)展而來(lái)的語(yǔ)言,它本身是完全兼容C語(yǔ)言的,也就是說(shuō),C語(yǔ)言的動(dòng)態(tài)內(nèi)存管理方式在C++中依舊可以正常使用。那它為什么還要設(shè)計(jì)一套屬于自己的動(dòng)態(tài)內(nèi)存管理方式呢?
在C++中,使用malloc/free申請(qǐng)或釋放內(nèi)置類(lèi)型的空間并沒(méi)有任何問(wèn)題,但我們知道C++引入了類(lèi)和對(duì)象的概念,而這一點(diǎn)帶來(lái)的影響就是并不能使用malloc從堆上為對(duì)象申請(qǐng)空間,因?yàn)閙alloc并不會(huì)去主動(dòng)的去調(diào)用構(gòu)造函數(shù),這意味著其并不能成為真正的對(duì)象。所以如果使用malloc只是申請(qǐng)了一段和對(duì)象同樣大小的空間而言,并非對(duì)象。同理使用free并不能釋放堆上對(duì)象的空間,因?yàn)閒ree并不會(huì)調(diào)用析構(gòu)函數(shù)去釋放對(duì)象中的資源。
而且C++所提供的動(dòng)態(tài)內(nèi)存管理方式使用起來(lái)更加方便、簡(jiǎn)單,對(duì)用戶(hù)更加友好,并且不用去擔(dān)心空間可能會(huì)申請(qǐng)失敗的情況。
new操作符的格式:
new 類(lèi)型; new 類(lèi)型(初值); new 類(lèi)型[];
delete操作符的格式:
delete 指針變量; delete[] 指針變量;
int main(){ int *p1 = new int; //動(dòng)態(tài)申請(qǐng)一個(gè)int類(lèi)型的空間 int *p2 = new int(10); //動(dòng)態(tài)申請(qǐng)一個(gè)int類(lèi)型的空間并初始化為10 int *p3 = new int[3]; //動(dòng)態(tài)申請(qǐng)10個(gè)int類(lèi)型的空間 //釋放申請(qǐng)的空間 delete p1; delete p2; delete[] p3; return 0; }
//定義一個(gè)簡(jiǎn)單的類(lèi) class Data{ public: //構(gòu)造函數(shù) Data(int data = 0) : _data(data) { cout << "Data() :" << this << endl; } //析構(gòu)函數(shù) ~Data() { cout << "~Data() : " << this << endl; } private: int _data; }; int main() { Data *d1 = new Data; //申請(qǐng)單個(gè)Data類(lèi)型的對(duì)象 Data *d2 = new Data(10); //申請(qǐng)單個(gè)Data類(lèi)型的對(duì)象并初始化 Data *d3 = new Data[5]; //申請(qǐng)5個(gè)Data類(lèi)型的對(duì)象 //依次釋放申請(qǐng)的對(duì)象資源 delete d1; delete d2; delete[] d3; //使用new/delete為類(lèi)對(duì)象申請(qǐng)或釋放空間時(shí)會(huì)主動(dòng)調(diào)用構(gòu)造函數(shù)/析構(gòu)函數(shù)完成對(duì)象的構(gòu)造/資源的清理。 return 0; }
new 和 delete在堆上申請(qǐng)和釋放空間的時(shí)候,在底層實(shí)際上調(diào)用的是operator new和operator delete兩個(gè)全局函數(shù)。
而operator new和operator delete最終還是調(diào)用malloc和free來(lái)申請(qǐng)和釋放空間。
1)new/delete內(nèi)置類(lèi)型的原理
如果申請(qǐng)的是內(nèi)置類(lèi)型的空間,new和malloc,delete和free基本類(lèi)似,不同的地方是:new/delete申請(qǐng)和釋放的是單個(gè)元素的空間,new[]和delete[]申請(qǐng)的是連續(xù)空間,而且new在申請(qǐng)空間失敗時(shí)會(huì)拋異常,malloc會(huì)返回NULL。也就是說(shuō)使用new操作符不需要進(jìn)行判空。
2)new/delete自定義類(lèi)型的原理
new的原理
1.調(diào)用operator new函數(shù)申請(qǐng)空間
2.在申請(qǐng)的空間上執(zhí)行構(gòu)造函數(shù),完成對(duì)象的構(gòu)造
delete的原理
1.在空間上執(zhí)行析構(gòu)函數(shù),完成對(duì)象中資源的清理工作
2.調(diào)用operator delete函數(shù)釋放對(duì)象的空間
new[]的原理
1.調(diào)用operator new[]函數(shù),在operator new[]中實(shí)際調(diào)用operator new函數(shù)完成N個(gè)對(duì)象空間的申請(qǐng)
2.在申請(qǐng)的空間上執(zhí)行N次構(gòu)造函數(shù)
delete[]的原理
1.在釋放的對(duì)象空間上執(zhí)行N次析構(gòu)函數(shù),完成N個(gè)對(duì)象中資源的清理
2.調(diào)用operator delete[]釋放空間,在operator delete[]中實(shí)際調(diào)用operator delete來(lái)釋放空間
都是從堆上申請(qǐng)空間,并且需要用戶(hù)手動(dòng)釋放。
1.malloc和free是函數(shù),new和delete是C++中的操作符
2.malloc申請(qǐng)的空間不會(huì)初始化,new可以初始化
3.malloc申請(qǐng)空間時(shí),需要手動(dòng)計(jì)算空間大小并傳遞,new只需在其后跟上類(lèi)型即可
4.malloc的返回值為void * , 在使用時(shí)必須強(qiáng)轉(zhuǎn),new不需要,因?yàn)閚ew后跟的是空間的類(lèi)型
5.malloc申請(qǐng)空間失敗時(shí),返回的是NULL,因此使用時(shí)必須判空,new不需要,但是new需要捕獲異常
6.申請(qǐng)自定義類(lèi)型對(duì)象時(shí),malloc/free只會(huì)開(kāi)辟空間,不會(huì)調(diào)用構(gòu)造函數(shù)與析構(gòu)函數(shù),而new在申請(qǐng)空間后會(huì)調(diào)用構(gòu)造函數(shù)完成對(duì)象的初始化,delete在釋放空間前會(huì)調(diào)用析構(gòu)函數(shù)完成空間中資源的清理
內(nèi)存泄漏是指你向系統(tǒng)申請(qǐng)分配內(nèi)存進(jìn)行使用(new/malloc),然后系統(tǒng)在堆內(nèi)存中給這個(gè)對(duì)象申請(qǐng)一塊內(nèi)存空間,但當(dāng)我們使用完了卻沒(méi)有歸還給系統(tǒng)(delete),導(dǎo)致這個(gè)不使用的對(duì)象一直占據(jù)內(nèi)存單元,造成系統(tǒng)將不能再把它分配給需要的程序。
一次內(nèi)存泄漏的危害可以忽略不計(jì),但是內(nèi)存泄漏堆積則后果很?chē)?yán)重,無(wú)論多少內(nèi)存,遲早會(huì)被占完,造成內(nèi)存泄漏。
以上是“C++中動(dòng)態(tài)內(nèi)存管理的示例分析”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對(duì)大家有所幫助,如果還想學(xué)習(xí)更多知識(shí),歡迎關(guān)注億速云行業(yè)資訊頻道!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。