版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
第一文詳解C++中動態(tài)內(nèi)存管理目錄前言1、C/C++程序的內(nèi)存開辟2.C語言中動態(tài)內(nèi)存管理方式:malloc/calloc/realloc/free2.1malloc、calloc、realloc區(qū)別?3.C++內(nèi)存管理方式3.1new/delete操作內(nèi)置類型3.2new和delete操作自定義類型3.3new和malloc處理失敗4.operatornew與operatordelete函數(shù)4.1operatornew與operatordelete函數(shù)4.1.1我們看看operatornew庫里面的源碼4.1.2operatordelete庫里面的源碼4.1.3operatornew和operatordelete的價值(重點)4.2重載operatornew與operatordelete(了解)5.new和delete的實現(xiàn)原理5.1內(nèi)置類型5.2自定義類型5.2.1new原理5.2.2delete原理5.2.3newT[N]原理5.2.4delete[]原理6.malloc/free和new/delete的異同6.1malloc/free和new/delete的共同點6.2malloc/free和new/delete的不同點
前言
在我們?nèi)粘懘a的過程中,我們對內(nèi)存空間的需求有時候在程序運行的時候才能知道,這時候我們就需要使用動態(tài)開辟內(nèi)存的方法。
1、C/C++程序的內(nèi)存開辟
首先我們先了解一下C/C++程序內(nèi)存分配的幾個區(qū)域:
intglobalVar=1;
staticintstaticGlobalVar=1;
voidTest()
staticintstaticVar=1;
intlocalVar=1;
intnum1[10]={1,2,3,4};
charchar2[]="abcd";
constchar*pChar3="abcd";
int*ptr1=(int*)malloc(sizeof(int)*4);
int*ptr2=(int*)calloc(4,sizeof(int));
int*ptr3=(int*)realloc(ptr2,sizeof(int)*4);
free(ptr1);
free(ptr3);
}
1.棧區(qū)(stack):在執(zhí)行函數(shù)時,函數(shù)內(nèi)局部變量的存儲單元都可以在棧上創(chuàng)建,函數(shù)執(zhí)行結(jié)束時這些存儲單元自動被釋放。棧內(nèi)存分配運算內(nèi)置于處理器的指令集中,效率很高,但是分配的內(nèi)存容量有限。棧區(qū)主要存放運行函數(shù)而分配的局部變量、函數(shù)參數(shù)、返回數(shù)據(jù)、返回地址等。2.堆區(qū)(heap):一般由程序員分配釋放,若程序員不釋放,程序結(jié)束時可能由OS回收。分配方式類似于鏈表。3.數(shù)據(jù)段(靜態(tài)區(qū))(static)存放全局變量、靜態(tài)數(shù)據(jù)。程序結(jié)束后由系統(tǒng)釋放。4.代碼段:存放函數(shù)體(類成員函數(shù)和全局函數(shù))的二進(jìn)制代碼。
這幅圖中,我們可以發(fā)現(xiàn)普通的局部變量是在棧上分配空間的,在棧區(qū)中創(chuàng)建的變量出了作用域去就會自動銷毀。但是被static修飾的變量是存放在數(shù)據(jù)段(靜態(tài)區(qū)),在數(shù)據(jù)段上創(chuàng)建的變量直到程序結(jié)束才銷毀,所以數(shù)據(jù)段上的數(shù)據(jù)生命周期變長了。
2.C語言中動態(tài)內(nèi)存管理方式:malloc/calloc/realloc/free
在C語言中,我們經(jīng)常會用到malloc,calloc和realloc來進(jìn)行動態(tài)的開辟內(nèi)存;同時,C語言還提供了一個函數(shù)free,專門用來做動態(tài)內(nèi)存的釋放和回收。其中他們?nèi)齻€的區(qū)別也是我們需要特別所強調(diào)區(qū)別的。
2.1malloc、calloc、realloc區(qū)別?
malloc函數(shù)是向內(nèi)存申請一塊連續(xù)可用的空間,并返回指向這塊空間的指針。
calloc與malloc的區(qū)別只在于calloc會在返回地址之前把申請的空間的每個字節(jié)初始化為0。
realloc函數(shù)可以做到對動態(tài)開辟內(nèi)存大小的調(diào)整。
我們通過這三個函數(shù)的定義也可以進(jìn)行功能的區(qū)分:
voidTest()
int*p1=(int*)malloc(sizeof(int));
free(p1);
int*p2=(int*)calloc(4,sizeof(int));
int*p3=(int*)realloc(p2,sizeof(int)*10);
free(p3);
}
3.C++內(nèi)存管理方式
我們都知道,C++語言是兼容C語言的,因此C語言中內(nèi)存管理方式在C++中可以繼續(xù)使用。但是有些地方就無能為力了,并且使用起來也可能比較麻煩。因此,C++擁有自己的內(nèi)管管理方式:通過new和delete操作符進(jìn)行動態(tài)內(nèi)存管理。
3.1new/delete操作內(nèi)置類型
intmain()
//動態(tài)申請一個int類型的空間
int*ptr1=newint;
//動態(tài)申請一個int類型的空間并初始化為10
int*ptr2=newint(10);
//動態(tài)申請3個int類型的空間(數(shù)組)
int*ptr3=newint[3];
//動態(tài)申請3個int類型的空間,初始化第一個空間值為1
int*ptr4=newint[3]{1};
deleteptr1;
deleteptr2;
delete[]ptr3;
delete[]ptr4;
return0;
}
我們首先通過畫圖分析進(jìn)行剖析代碼:
我們在監(jiān)視窗口看看這3個變量
注意:申請和釋放單個元素的空間,使用new和delete操作符,申請和釋放連續(xù)的空間,使用new[]和delete[],要匹配起來使用。
3.2new和delete操作自定義類型
classA{
public:
A(inta=0)
:_a(a)
cout"A():"thisendl;
cout"~A():"thisendl;
private:
int_a;
intmain()
A*p1=(A*)malloc(sizeof(A));
A*p2=newA(1);
free(p1);
deletep2;
return0;
}
在這段代碼中,p1是我們使用malloc開辟的,p2是通過new來開辟的。我們編譯運行這段代碼。
發(fā)現(xiàn)輸出了這兩句,那這兩句是誰調(diào)用的呢我們通過調(diào)試逐語句來分析這個過程
內(nèi)置類型區(qū)別
注意:在申請自定義類型的空間時,new會自動調(diào)用構(gòu)造函數(shù),delete時會調(diào)用析構(gòu)函數(shù),而malloc和free不會。
3.3new和malloc處理失敗
intmain()
void*p0=malloc(1024*1024*1024);
coutp0endl;
//malloc失敗,返回空指針
void*p1=malloc(1024*1024*1024);
coutp1endl;
//new失敗,拋異常
void*p2=newchar[1024*1024*1024];
coutp2endl;
catch(constexceptione)
coute.what()endl;
return0;
}
我們能夠發(fā)現(xiàn),malloc失敗時會返回空指針,而new失敗時,會拋出異常。
4.operatornew與operatordelete函數(shù)
4.1operatornew與operatordelete函數(shù)
C++標(biāo)準(zhǔn)庫還提供了operatornew和operatordelete函數(shù),但是這兩個函數(shù)并不是對new和delete的重載,operatornew和operatordelete是兩個庫函數(shù)。(這里C++大佬設(shè)計時這樣取名確實很容易混淆)
4.1.1我們看看operatornew庫里面的源碼
void*__CRTDECLoperatornew(size_tsize)_THROW1(_STDbad_alloc){
//trytoallocatesizebytes
void*p;
while((p=malloc(size))==0)
if(_callnewh(size)==0)
//reportnomemory
//如果申請內(nèi)存失敗了,這里會拋出bad_alloc類型異常
staticconststd::bad_allocnomem;
_RAISE(nomem);
return(p);
}
庫里面operatornew的作用是封裝了malloc,如果malloc失敗,拋出異常。
4.1.2operatordelete庫里面的源碼
該函數(shù)最終是通過free來釋放空間的
//operatordelete源碼
voidoperatordelete(void*pUserData){
_CrtMemBlockHeader*pHead;
RTCCALLBACK(_RTC_Free_hook,(pUserData,0));
if(pUserData==NULL)
return;
_mlock(_HEAP_LOCK);/*blockotherthreads*/
__TRY
/*getapointertomemoryblockheader*/
pHead=pHdr(pUserData);
/*verifyblocktype*/
_ASSERTE(_BLOCK_TYPE_IS_VALID(pHead-nBlockUse));
_free_dbg(pUserData,pHead-nBlockUse);
__FINALLY
_munlock(_HEAP_LOCK);/*releaseotherthreads*/
__END_TRY_FINALLY
return;
free的實現(xiàn)
#definefree(p)_free_dbg(p,_NORMAL_BLOCK)
4.1.3operatornew和operatordelete的價值(重點)
classA{
public:
A(inta=0)
:_a(a)
cout"A():"thisendl;
cout"~A():"thisendl;
private:
int_a;
intmain()
//跟malloc功能一樣,失敗以后拋出異常
A*ps1=(A*)operatornew(sizeof(A));
operatordelete(ps1);
A*ps2=(A*)malloc(sizeof(A));
free(ps2);
A*ps3=newA;
deleteps3;
return0;
}
我們使用new的時候,new要開空間,要調(diào)用構(gòu)造函數(shù)。new可以轉(zhuǎn)換成callmalloc,call構(gòu)造函數(shù)。但是callmalloc一旦失敗,會返回空指針或者錯誤碼。在面向?qū)ο蟮恼Z言中更喜歡使用異常。而operatornew相比較malloc的不同就在于如果一旦失敗會拋出異常,因此new的底層實現(xiàn)是調(diào)用operatornew,operatornew會調(diào)用malloc(如果失敗拋出異常),再調(diào)用構(gòu)造函數(shù)。
我們通過匯編看一下ps3
operatordelete同理。
總結(jié):通過上述兩個全局函數(shù)的實現(xiàn)知道,operatornew實際也是通過malloc來申請空間,如果malloc申請空間成功就直接返回,否則執(zhí)行用戶提供的空間不足應(yīng)對措施,如果用戶提供該措施就繼續(xù)申請,否則就拋異常。operatordelete最終是通過free來釋放空間的。
4.2重載operatornew與operatordelete(了解)
專屬的operatornew技術(shù),提高效率。應(yīng)用:內(nèi)存池
classA{
public:
A(inta=0)
:_a(a)
cout"A():"thisendl;
//專屬的operatornew
void*operatornew(size_tn)
void*p=nullptr;
p=allocatorA().allocate(1);
cout"memorypoolallocate"endl;
returnp;
voidoperatordelete(void*p)
allocatorA().deallocate((A*)p,1);
cout"memorypooldeallocate"endl;
cout"~A():"thisendl;
private:
int_a;
intmain()
intn=0;
cinn;
for(inti=0;i++i)
A*ps1=newA;//operatornew+A的構(gòu)造函數(shù)
return0;
}
注意:一般情況下不需要對operatornew和operatordelete進(jìn)行重載,除非在申請和釋放空間時候有某些特殊的需求。比如:在使用new和delete申請和釋放空間時,打印一些日志信息,可以簡單幫助用戶來檢測是否存在內(nèi)存泄漏。
5.new和delete的實現(xiàn)原理
5.1內(nèi)置類型
如果申請的是內(nèi)置類型的空間,new和malloc,delete和free基本類似,不同的地方是:new/delete申請和釋放的是單個元素的空間,new[]和delete[]申請的是連續(xù)空間,而且new在申請空間失敗時會拋異常,malloc會返回NULL。
5.2自定義類型
5.2.1new原理
1、調(diào)用operatornew函數(shù)申請空間2、再調(diào)用構(gòu)造函數(shù),完成對對象的構(gòu)造。
5.2.2delete原理
1、先調(diào)用析構(gòu)函數(shù),完成對對象中資源的清理工作。2、調(diào)用operatordelete函數(shù)釋放對象的空間
5.
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- ct室質(zhì)量與安全教育培訓(xùn)制度
- 兩個體系培訓(xùn)學(xué)習(xí)制度
- 培訓(xùn)計劃執(zhí)行管理制度
- 艾灸養(yǎng)生館培訓(xùn)制度
- 藥店宣傳培訓(xùn)制度及流程
- 飛機維修師培訓(xùn)制度
- 黨支部職工培訓(xùn)制度
- 安裝公司員工培訓(xùn)制度
- 培訓(xùn)學(xué)校教學(xué)計劃制度
- 培訓(xùn)機構(gòu)基本管理制度
- GB/T 17213.4-2015工業(yè)過程控制閥第4部分:檢驗和例行試驗
- FZ/T 73009-2021山羊絨針織品
- JJF 1069-2012 法定計量檢定機構(gòu)考核規(guī)范(培訓(xùn)講稿)
- GB∕T 5900.2-2022 機床 主軸端部與卡盤連接尺寸 第2部分:凸輪鎖緊型
- 2011-2015廣汽豐田凱美瑞維修手冊wdl
- DFMEA編制作業(yè)指導(dǎo)書新版
- KTronics籃輸送式洗碗碟機操作手冊
- DB35∕T 1844-2019 高速公路邊坡工程監(jiān)測技術(shù)規(guī)程
- 城市管理綜合執(zhí)法局城管執(zhí)法與執(zhí)法程序PPT模板
- 閥門基礎(chǔ)知識上
- 第二章注射成型工藝與模具結(jié)構(gòu)
評論
0/150
提交評論