1. 前言
在學(xué)習(xí)C語言的時(shí)候,我們學(xué)習(xí)了動(dòng)態(tài)內(nèi)存管理,也就是在堆上動(dòng)態(tài)開辟一些內(nèi)存供我們使用,雖然C語言內(nèi)存管理的方法在C++中也可以使用,但還有一些地方是他無能為力的,所以我們今天來學(xué)習(xí)C++內(nèi)存管理的方式。
2. C/C++內(nèi)存分布
在學(xué)習(xí)內(nèi)存管理之前,我們先來認(rèn)識一下C/C++中程序內(nèi)存區(qū)域被劃分為哪些。
1.棧又叫堆棧,存儲非靜態(tài)局部變量 / 函數(shù)參數(shù) / 返回值等等,棧是向下增長的。
2.內(nèi)存映射段是高效的I / O映射方式,用于裝載一個(gè)共享的動(dòng)態(tài)內(nèi)存庫。用戶可使用系統(tǒng)接口創(chuàng)建共享共享內(nèi)存,做進(jìn)程間通信。
3.堆用于程序運(yùn)行時(shí)動(dòng)態(tài)內(nèi)存分配,堆是可以上增長的。
4.數(shù)據(jù)段,存儲全局?jǐn)?shù)據(jù)和靜態(tài)數(shù)據(jù)。
5.代碼段,存儲可執(zhí)行的代碼 / 只讀常量。
3. C語言動(dòng)態(tài)內(nèi)存管理方式
C語言中動(dòng)態(tài)內(nèi)存管理依靠的是4個(gè)函數(shù):malloc、realloc、calloc、free
這些函數(shù)具體的功能可以看博主之前發(fā)布的C語言動(dòng)態(tài)內(nèi)存管理文章,有詳細(xì)的講解
void Test()
{
int* p1 = (int*)malloc(sizeof(int));
free(p1);
int* p2 = (int*)calloc(4, sizeof(int));
int* p3 = (int*)realloc(p2, sizeof(int) * 10);
//這里不需要free(p2)
free(p3);
}
int main()
{
Test();
return 0;
}
4. C++內(nèi)存管理方式
C語言內(nèi)存管理方式在C++中可以繼續(xù)使用,但有些地方就無能為力,而且使用起來比較麻煩,因此C++又提出了自己的內(nèi)存管理方式:通過new和delete操作符進(jìn)行動(dòng)態(tài)內(nèi)存管理。
而new和delete對于內(nèi)置類型和自定義類型有不同的處理方式,下面我們來學(xué)習(xí)new和delete分別對內(nèi)置類型和自定義類型的處理方式。
4.1 內(nèi)置類型
針對內(nèi)置類型,new/delete跟malloc/free沒有本質(zhì)的區(qū)別,只有用法的區(qū)別,new/delete的用法簡化了。
下面我們直接舉例說明new和delete針對內(nèi)置類型的用法。
void Test()
{
//C語言
//動(dòng)態(tài)申請一個(gè)int類型的空間
int* p1 = (int*)malloc(sizeof(int));
//C++
//動(dòng)態(tài)申請一個(gè)int類型的空間
int* p2 = new int;
//申請5個(gè)int的數(shù)組
int* p3 = new int[5];
//申請1個(gè)int對象,初始化為5
int* p4 = new int(5);
//C++11支持new[] 用{}初始化 C++98不支持
int* p5 = new int[5]{1,2,3};
//C語言
free(p1);
//C++
delete p2;
delete[] p3;
delete p4;
delete[] p5;
}
int main()
{
Test();
return 0;
}
注意:申請和釋放單個(gè)元素的空間,使用new和delete操作符,申請和釋放連續(xù)的空間,使用new[]和delete[],一定要匹配起來使用。
4.2 自定義類型
在申請自定義類型的空間時(shí),new會(huì)調(diào)用構(gòu)造函數(shù),delete會(huì)調(diào)用析構(gòu)函數(shù),而malloc與free不會(huì)。
例如:
class A
{
public:
A(int a = 0)
:_a(a)
{
cout << "A():" << this << endl;
}
~A()
{
cout << "~A():" << this << endl;
}
private:
int _a;
};
int main()
{
//C語言
//malloc
//在堆上申請空間
A* p1 = (A*)malloc(sizeof(A));
if (p1 == NULL)
{
perror("malloc fail\n");
return 0;
}
//釋放空間
free(p1);
//C++
//new
//在堆上申請空間、調(diào)用構(gòu)造函數(shù)初始化
//A* p2 = new A;
A* p3 = new A(10);
//調(diào)用析構(gòu)函數(shù)清理對象中的資源、釋放空間
delete p3;
return 0;
}
總結(jié):new/delete和malloc/free最大區(qū)別是new/delete對于自定義類型除了開辟空間還會(huì)調(diào)用構(gòu)造函數(shù)和析構(gòu)函數(shù),對于內(nèi)置類型這兩者幾乎是一樣的。
5. operator new與operator delete函數(shù)
new和delete是用戶進(jìn)行動(dòng)態(tài)內(nèi)存申請和釋放的操作符。
operator new 和operator delete是系統(tǒng)提供的全局函數(shù)。
new在底層調(diào)用operator new全局函數(shù)來申請空間,delete在底層通過operator delete全局函數(shù)來釋放空間。
operator new:
該函數(shù)實(shí)際通過malloc來申請空間,當(dāng)malloc申請空間成功時(shí)直接返回,申請空間失敗時(shí),就嘗試執(zhí)行空間不足的應(yīng)對措施,如果該應(yīng)對措施用戶已經(jīng)設(shè)置了,就繼續(xù)申請,否則拋異常。
operator delete:
該函數(shù)最終是通過free來釋放空間的。
6. new和delete的實(shí)現(xiàn)原理
內(nèi)置類型:
如果申請的是內(nèi)置類型的空間,new和malloc,delete和free基本類似。
不同的是:
new/delete申請和釋放的是單個(gè)元素的空間,new[]和delete[]申請和釋放的是連續(xù)空間,而且new在申請空間失敗時(shí)會(huì)拋異常,malloc會(huì)返回NULL。
自定義類型:
new的原理:
1.調(diào)用operator new函數(shù)申請空間
2.在申請的空間上執(zhí)行構(gòu)造函數(shù),完成對象的構(gòu)造
delete的原理:
1.在空間上執(zhí)行析構(gòu)函數(shù),完成對象中資源的清理工作
2.調(diào)用operator delete函數(shù)釋放對象的空間
new T[N]的原理:
1.調(diào)用operator new[]函數(shù),在operator new[]中實(shí)際調(diào)用operator new函數(shù)完成N個(gè)對象空間的申請
2.在申請的空間上執(zhí)行N次構(gòu)造函數(shù)
delete[]的原理:
1.在釋放的對象空間上執(zhí)行N次析構(gòu)函數(shù),完成N個(gè)對象中資源的清理
2.調(diào)用operator delete[]釋放空間,實(shí)際在operator delete[]中調(diào)用operator delete函數(shù)來釋放空間
7. 定位new表達(dá)式(placement-new)
定位new表達(dá)式是在已分配的原始內(nèi)存空間中調(diào)用構(gòu)造函數(shù)初始化一個(gè)對象。
使用格式:
new (place_address) type或者new (place_address) type(initializer - list)
place_address必須是一個(gè)指針,initializer - list是類型的初始化列表
使用場景:
定位new表達(dá)式在實(shí)際中一般是配合內(nèi)存池使用。因?yàn)閮?nèi)存池分配出的內(nèi)存沒有初始化,所以如果是自定義類型的對象,需要使用new的定義表達(dá)式進(jìn)行顯示調(diào)構(gòu)造函數(shù)進(jìn)行初始化。文章來源:http://www.zghlxwxcb.cn/news/detail-459099.html
class A
{
public:
A(int a = 0)
: _a(a)
{
cout << "A():" << this << endl;
}
~A()
{
cout << "~A():" << this << endl;
}
private:
int _a;
};
int main()
{
A* p1 = new A;
A* p2 = (A*)malloc(sizeof(A));
if (p2 == nullptr)
{
perror("malloc fail");
return 0;
}
//new(p2)A;
new(p2)A(10);
return 0;
}
8. 結(jié)尾
C++內(nèi)存管理的方式我們就學(xué)習(xí)到這里,在學(xué)習(xí)了new和delete之后,我們以后還是盡量使用new和delete,因?yàn)閚ew和delete比起malloc和free不僅簡潔了很多,而且還更加實(shí)用和智能了。
最后,感謝各位大佬的耐心閱讀和支持,覺得本篇文章寫的不錯(cuò)的朋友可以三連關(guān)注支持一波,如果有什么問題或者本文有錯(cuò)誤的地方大家可以私信我,也可以在評論區(qū)留言討論,再次感謝各位。文章來源地址http://www.zghlxwxcb.cn/news/detail-459099.html
到了這里,關(guān)于【C++】——內(nèi)存管理(new和delete)的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!