網(wǎng)站架構(gòu)師的工作內(nèi)容最好的推廣平臺排名
C++:渴望力量嗎,少年?
文章目錄
- 一、C++內(nèi)存管理方式
- 1. new/delete操作內(nèi)置類型
- 2. new和delete操作自定義類型
- 二、operator new與operator delete函數(shù)
- 三、new和delete的實(shí)現(xiàn)原理
- 1. 內(nèi)置類型
- 2. 自定義類型
- 四、內(nèi)存泄漏
- 1. 什么是內(nèi)存泄漏
- 2. 內(nèi)存泄漏的危害
- 3. 堆內(nèi)存泄漏(Heap leak)
- 4. 解決方案
一、C++內(nèi)存管理方式
??C語言內(nèi)存管理方式在C++中可以繼續(xù)使用,但有些地方就無能為力,而且使用起來比較麻煩,因此C++又提出了自己的內(nèi)存管理方式:通過new和delete操作符進(jìn)行動態(tài)內(nèi)存管理。
1. new/delete操作內(nèi)置類型
int main()
{// 動態(tài)申請一個int類型的空間int* ptr4 = new int;// 動態(tài)申請一個int類型的空間并初始化為10 int* ptr5 = new int(10);// 動態(tài)申請10個int類型的空間int* ptr6 = new int[3];delete ptr4;delete ptr5; delete[] ptr6;// 額外支持開空間+初始化int* p6 = new int(10);//注意這里是賦值為10int* p7 = new int[10]{1,2,3};//和C語言一樣,這種情況下沒有初始化到的部分默認(rèn)為0int* p8 = new int[10]{};return 0;
}
2. new和delete操作自定義類型
??在申請自定義類型的空間時,new會調(diào)用構(gòu)造函數(shù),delete會調(diào)用析構(gòu)函數(shù),而malloc與free不會。而他們對內(nèi)置類型是幾乎是一樣的。
class A
{
public:A(int a = 0): _a(a){cout << "A():" << this << endl;}~A(){cout << "~A():" << this << endl;}private:int _a;
};
int main()
{// malloc沒有辦法很好支持動態(tài)申請的自定義對象初始化A* p1 = (A*)malloc(sizeof(A));//p1->_a = 0;//p1->A(1);// 自定義類型,開空間的同時調(diào)用構(gòu)造函數(shù)初始化A* p2 = new A;A* p3 = new A(3);// 自定義類型,調(diào)用析構(gòu)函數(shù)+釋放空間delete p2;delete p3;A* p4 = new A[10];delete[] p4;/*下面三種寫法都是一樣的A aa1(1);A aa2(2);A* p5 = new A[10]{ aa1, aa2 };delete[] p5;A* p6 = new A[10]{ A(1), A(2) };delete[] p6;A* p7 = new A[10]{ 1, 2 };delete[] p7;
*/return 0;
}
二、operator new與operator delete函數(shù)
??new和delete是用戶進(jìn)行動態(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申請空間成功時直接返回;申請空間失敗,嘗試執(zhí)行空間不足應(yīng)對措施,如果改應(yīng)對措施用戶設(shè)置了,則繼續(xù)申請,否則拋異常。
typedef char DataType;
class Stack
{
public:Stack(size_t capacity = 4){cout << "Stack()" << endl;_array = new DataType[capacity];//析構(gòu)函數(shù)對應(yīng)也得用delete釋放空間//_array = new char[0x7ffffffffff];//如果取消注釋,那么對應(yīng)的第二段代碼會拋出異常_capacity = capacity;_size = 0;}void Push(DataType data){// CheckCapacity();_array[_size] = data;_size++;}~Stack(){cout << "~Stack()" << endl;delete[] _array;_array = nullptr;_size = _capacity = 0;}
private:// 內(nèi)置類型DataType* _array;int _capacity;int _size;
};
class A
{
public:A(int a = 0):_a1(a){}~A(){cout << "~A()" << endl;}private:int _a1;
};
int main()
{Stack* pst1 = (Stack*)operator new(sizeof(Stack));//相當(dāng)于malloc,創(chuàng)造它是為了符合拋出異常的方式operator delete(pst1);//相當(dāng)于free//其實(shí)上面兩個函數(shù)主要都不是讓我們直接使用,而是分別封裝在new和delete中,new就相當(dāng)于operator new和調(diào)用構(gòu)造函數(shù)Stack* pst2 = new Stack;delete pst2;//free(pst2);A* p2 = new A[10];delete[] p2;return 0;
}
??new和delete一定要匹配使用,否則后果可能是未定義的!!!
三、new和delete的實(shí)現(xiàn)原理
1. 內(nèi)置類型
??如果申請的是內(nèi)置類型的空間,new和malloc,delete和free基本類似,不同的地方是:new / delete申請和釋放的是單個元素的空間,new[]和delete[]申請的是連續(xù)空間,而且new在申請空間失敗時會拋異常,malloc會返回NULL。
2. 自定義類型
(1)new的原理
? ? a.調(diào)用operator new函數(shù)申請空間
? ? b.在申請的空間上執(zhí)行構(gòu)造函數(shù),完成對象的構(gòu)造
(2)delete的原理
? ? a.在空間上執(zhí)行析構(gòu)函數(shù),完成對象中資源的清理工作
? ? b.調(diào)用operator delete函數(shù)釋放對象的空間
(3)new T[N]的原理
? ? a.調(diào)用operator new[]函數(shù),在operator new[]中實(shí)際調(diào)用operator new函數(shù)完成N個對象空間的申請
? ? b.在申請的空間上執(zhí)行N次構(gòu)造函數(shù)
(4)delete[]的原理
? ? a.在釋放的對象空間上執(zhí)行N次析構(gòu)函數(shù),完成N個對象中資源的清理
? ? b.調(diào)用operator delete[]釋放空間,實(shí)際在operator delete[]中調(diào)用operator delete來釋放空間
四、內(nèi)存泄漏
1. 什么是內(nèi)存泄漏
??內(nèi)存泄漏指因?yàn)槭韬龌蝈e誤造成程序未能釋放已經(jīng)不再使用的內(nèi)存的情況。內(nèi)存泄漏并不是指內(nèi)存在物理上的消失,而是應(yīng)用程序分配某段內(nèi)存后,因?yàn)樵O(shè)計(jì)錯誤,失去了對該段內(nèi)存的控制,因而造成了內(nèi)存的浪費(fèi)。
2. 內(nèi)存泄漏的危害
??長期運(yùn)行的程序出現(xiàn)內(nèi)存泄漏,影響很大,如操作系統(tǒng)、后臺服務(wù)等等,出現(xiàn)內(nèi)存泄漏會導(dǎo)致響應(yīng)越來越慢,最終卡死。
void MemoryLeaks()
{// 1.內(nèi)存申請了忘記釋放int* p1 = (int*)malloc(sizeof(int)); int* p2 = new int;// 2.異常安全問題int* p3 = new int[10];Func(); // 這里Func函數(shù)拋異常導(dǎo)致 delete[] p3未執(zhí)行,p3沒被釋放. delete[] p3;
}
3. 堆內(nèi)存泄漏(Heap leak)
??作為初學(xué)者,我們更加關(guān)注的是這方面的泄露。堆內(nèi)存指的是程序執(zhí)行中依據(jù)須要分配通過malloc / calloc / realloc / new等從堆中分配的一塊內(nèi)存,用完后必須通過調(diào)用相應(yīng)的 free或者delete 刪掉。假設(shè)程序的設(shè)計(jì)錯誤導(dǎo)致這部分內(nèi)存沒有被釋放,那么以后這部分空間將無法再被使用,就會產(chǎn)生Heap Leak。
4. 解決方案
內(nèi)存泄漏非常常見,一般解決方案分為兩種:
(1)事前預(yù)防型。如智能指針等;
(2)事后查錯型。如泄漏檢測工具。