c++动态内存管理
c/c++內(nèi)存分布
虛擬地址空間分布
為什么操作系統(tǒng)要?jiǎng)澐诌@些區(qū)段
答:為了找數(shù)據(jù),存數(shù)據(jù)方便
以下的代碼分別在虛擬地址空間中的哪個(gè)段
int globalVar = 1; //數(shù)據(jù)段static int staticGlobalVar = 1; //數(shù)據(jù)段void Test() { static int staticVar = 1; //數(shù)據(jù)端int localVar = 1; //棧int num1[10] = {1, 2, 3, 4}; //棧char char2[] = "abcd"; //char數(shù)組在棧,里面存儲(chǔ)的abcd字符串常量在代碼段char* pChar3 = "abcd"; //pChar指針在棧上,里面的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);}sizeof與strlen的區(qū)別
c語(yǔ)言動(dòng)態(tài)開(kāi)辟空間
動(dòng)態(tài)申請(qǐng)空間的方式
相同點(diǎn):
- 都是從堆上開(kāi)辟空間
- 返回值類型都是void*
- 申請(qǐng)空間失敗,返回的都是NULL
- 申請(qǐng)的空間都需要手動(dòng)釋放
- 在接收返回值時(shí)都需要進(jìn)行強(qiáng)制類型轉(zhuǎn)換
不同點(diǎn)
malloc:
- 參數(shù):字節(jié)數(shù),
- 不會(huì)對(duì)申請(qǐng)的空間進(jìn)行初始化,
- 在接收返回值時(shí)必須強(qiáng)制類型轉(zhuǎn)換
- 如果申請(qǐng)空間失敗,返回值NULL,使用前必須判斷是否為空
calloc:
- 參數(shù)列表不同:void * calloc ( size_t num, size_t size );,第一個(gè)為元素個(gè)數(shù),第二個(gè)為單個(gè)元素大小
- 函數(shù)功能差異:calloc會(huì)將申請(qǐng)的空間初始化為0
realloc
- 參數(shù)列表:void * realloc ( void * ptr, size_t size );
- 函數(shù)功能:將ptr所指向的空間調(diào)整到size字節(jié),如果ptr為空----->函數(shù)行為與malloc相同
- ptr非空,判斷是縮小還是增大,縮小的話,對(duì)原空間進(jìn)行調(diào)整,最后返回該空間的首地址,擴(kuò)大的話,有兩種情況:1. 擴(kuò)大一點(diǎn),2.擴(kuò)大很多
動(dòng)態(tài)釋放方式
手動(dòng)free
malloc
int* p =(int*)malloc(10*sizeof(int));40字節(jié)-----堆上,只要把空間分配給一個(gè)應(yīng)用程序,那么其他應(yīng)用程序就用不了。系統(tǒng)必須對(duì)malloc申請(qǐng)的空間進(jìn)行管理。
一般malloc申請(qǐng)空間時(shí),比如申請(qǐng)40個(gè)字節(jié),除了申請(qǐng)的40字節(jié)空間,他還會(huì)在前面加一個(gè)結(jié)構(gòu)體來(lái)管理40字節(jié)的空間,在后面加4個(gè)字節(jié)的空間用來(lái)防止越界
詳解c中動(dòng)態(tài)內(nèi)存分配
C++內(nèi)存管理方式
C語(yǔ)言內(nèi)存管理方式在C++中可以繼續(xù)使用,但有些地方就無(wú)能為力而且使用起來(lái)比較麻煩,因此C++又提出 了自己的內(nèi)存管理方式:通過(guò)new和delete操作符進(jìn)行動(dòng)態(tài)內(nèi)存管理。
new申請(qǐng)內(nèi)置類型
int main() {//new 申請(qǐng)單個(gè)類型元素的空間----默認(rèn)情況下new出的空間在堆上int *p1 = new int;int *p2 = new int(10);int *p3 = new int[10];int *p4 = new int[10]{1, 2, 3, 4, 5, 6, 7, 8, 9, 0};delete p1;delete p2;delete[] p3;delete[] p4;return 0; }注意:申請(qǐng)和釋放單個(gè)元素的空間,使用new和delete操作符,申請(qǐng)和釋放連續(xù)的空間,使用new[]和 delete[]
如果沒(méi)有匹配
如果申請(qǐng)的是內(nèi)置類型的空間,沒(méi)有匹配的話,不會(huì)產(chǎn)生任何后果
void Test() {int *p1 = (int *)malloc(sizeof(int)* 4);int *p2 = (int *)malloc(sizeof(int)* 4);delete p1;delete p2;int *p3 = new int;int *p4 = new int;free(p3);delete[]p4;int *p5 = new int[10];int *p6 = new int[10];free(p5);delete p6; }new申請(qǐng)自定義類型數(shù)據(jù)
未進(jìn)行匹配使用
//自定義類型 class Test { public:Test(){_data = 10;cout << "Test():" << this <<endl;}~Test(){cout << "~Test()" << this << endl;} private:int _data;};void Test2() {Test *p1 = (Test *)malloc(sizeof(Test)* 4);//Test *p2 = (Test *)malloc(sizeof(Test)* 4);delete p1;//delete[] p2;Test *p3 = new Test;Test *p4 = new Test;free(p3);delete[]p4;Test *p5 = new Test[10];Test *p6 = new Test[10];free(p5);delete p6; }operator new與operator delete函數(shù)
new是先調(diào)用構(gòu)造函數(shù),還是先申請(qǐng)空間?
第一件事情:申請(qǐng)內(nèi)存空間,第二才是調(diào)用構(gòu)造函數(shù),完成對(duì)象的初始化
new和delete是用戶進(jìn)行動(dòng)態(tài)內(nèi)存申請(qǐng)和釋放的操作符,operator new 和operator delete是系統(tǒng)提供的 全局函數(shù),new在底層調(diào)用operator new全局函數(shù)來(lái)申請(qǐng)空間,delete在底層通過(guò)operator delete全局 函數(shù)來(lái)釋放空間。
循環(huán)調(diào)用malloc來(lái)不斷申請(qǐng)空間,直到申請(qǐng)成功,
delete p;
總結(jié)
operator new 實(shí)際也是通過(guò)malloc來(lái)申請(qǐng)空間,如果malloc申請(qǐng)空間 成功就直接返回,否則執(zhí)行用戶提供的空間不足應(yīng)對(duì)措施,如果用戶提供該措施就繼續(xù)申請(qǐng),否則就拋異 常。operator delete 最終是通過(guò)free來(lái)釋放空間的
void* operator new(size_t size,const char* file,const char* funname,size_t line) {cout << file << "-" << funname << "-" << line << "-" << size << endl;return malloc(size); }void operator delete(void *p, const char* file, const char* funname, size_t line) {cout << file << "-" << funname << "-" << line << "-" << endl;free(p); } #define new new(__FILE__, __FUNCDNAME__, __LINE__)int main() {int *p = new int;delete p;system("pause");return 0; }new和delete的實(shí)現(xiàn)原理
內(nèi)置類型
如果申請(qǐng)的是內(nèi)置類型的空間,new和malloc,delete和free基本類似,不同的地方是:new/delete申請(qǐng)和 釋放的是單個(gè)元素的空間,new[]和delete[]申請(qǐng)的是連續(xù)空間,而且new在申請(qǐng)空間失敗時(shí)會(huì)拋異常, malloc會(huì)返回NULL
自定義類型
- new的原理
- 調(diào)用operator new函數(shù)申請(qǐng)空間
- 在申請(qǐng)的空間上執(zhí)行構(gòu)造函數(shù),完成對(duì)象的構(gòu)造
- delete的原理
- 在空間上執(zhí)行析構(gòu)函數(shù),完成對(duì)象中資源的清理工作
- 調(diào)用operator delete函數(shù)釋放對(duì)象的空間
- new T[N]的原理
- 調(diào)用operator new[]函數(shù),在operator new[]中實(shí)際調(diào)用operator new函數(shù)完成N個(gè)對(duì)象空間的申 請(qǐng)
- 在申請(qǐng)的空間上執(zhí)行N次構(gòu)造函數(shù)
- delete[]的原理
- 在釋放的對(duì)象空間上執(zhí)行N次析構(gòu)函數(shù),完成N個(gè)對(duì)象中資源的清理
- 調(diào)用operator delete[]釋放空間,實(shí)際在operator delete[]中調(diào)用operator delete來(lái)釋放空間
內(nèi)存碎片化
如果每回一小塊一小塊申請(qǐng)內(nèi)存,就會(huì)造成內(nèi)存的浪費(fèi)。所以c++有一個(gè)現(xiàn)成的內(nèi)存池就是空間配置器
以下代碼對(duì)鏈表的節(jié)點(diǎn)ListNode通過(guò)重載類專屬 operator new/ operator delete,實(shí)現(xiàn)鏈表節(jié) 點(diǎn)使用內(nèi)存池申請(qǐng)和釋放內(nèi)存,提高效率。
定位new表達(dá)式
在已經(jīng)存在的空間上執(zhí)行構(gòu)造函數(shù)
使用格式:
new (place_address) type或者new (place_address) type(initializer-list)
place_address必須是一個(gè)指針,initializer-list是類型的初始化列表
使用場(chǎng)景:
定位new表達(dá)式在實(shí)際中一般是配合內(nèi)存池使用。因?yàn)閮?nèi)存池分配出的內(nèi)存沒(méi)有初始化,所以如果是自定義類型的對(duì)象,需要使用new的定義表達(dá)式進(jìn)行顯示調(diào)構(gòu)造函數(shù)進(jìn)行初始化
關(guān)于c++動(dòng)態(tài)管理方面的題目
題目總結(jié)的鏈接
總結(jié)
- 上一篇: 大力女都奉顺剧情介绍
- 下一篇: c++动态内存管理题目