柚子快報激活碼778899分享:【C++初階】內(nèi)存管理
柚子快報激活碼778899分享:【C++初階】內(nèi)存管理
目錄
C++內(nèi)存分布
C++內(nèi)存管理方式
new和delete
對內(nèi)置類型的使用
對自定義類型的使用
原理
內(nèi)置類型:
自定義類型:
匹配問題
內(nèi)置類型:
自定義類型:
意義:
1、析構(gòu)函數(shù)調(diào)用次數(shù)
2、錯誤位置釋放
注:不需要匹配的情況
new/delete和malloc/free的區(qū)別
C++內(nèi)存分布
C++內(nèi)存管理方式
new和delete
C語言的內(nèi)存管理方法在C++中也可以使用,但是在一些地方是無法處理的而且使用起來會比較麻煩,所以C++就提出了自己的管理方法:new和delete
對內(nèi)置類型的使用
int main()
{
int* a1 = new int;//動態(tài)申請一個int類型的空間
delete a1;//釋放空間
int* a2 = new int(1);//動態(tài)申請一個int類型的空間,并初始化為1
delete a2;
int* a3 = new int[10];//動態(tài)申請十個int類型的空間
delete[] a3;
return 0;
}
對于連續(xù)申請的多個空間的初始化
int main()
{
int* a = new int[10]{1,2,3};//動態(tài)申請十個int類型的空間,初始化前三個,其他的自動賦值為0
delete[] a3;
return 0;
}
對自定義類型的使用
class A
{
public:
A(int a)
{
_a1 = _a2 = a;
}
~A()
{
cout << "~A()" << endl;
}
private:
int _a1;
int _a2;
};
int main()
{
A* a1 = new A;
delete a1;
A* a2 = new A(1);
delete a2;
A* a3 = new A[10]{1,2,3};
delete[] a3;
return 0;
}
與內(nèi)置類型不同的是,new/delete對于自定義類型對象不僅會開辟/釋放空間,還會調(diào)用構(gòu)造函數(shù)和析構(gòu)函數(shù),初始化了幾個就調(diào)用幾次構(gòu)造函數(shù)和對應(yīng)的析構(gòu)函數(shù)
class A
{
public:
A(int a)
{
_a1 = _a2 = a;
}
A(int a1 = 0, int a2 = 0)
{
cout << "A()" << endl;
_a1 = a1;
_a2 = a2;
}
~A()
{
cout << "~A()" << endl;
}
private:
int _a1;
int _a2;
};
int main()
{
A* a = new A[10]{{1,1},{2,2},{3,3}};
delete[] a;
return 0;
}
在這里a的實現(xiàn)要依靠默認構(gòu)造函數(shù)/或?qū)?yīng)有參構(gòu)造函數(shù),如果沒有的話就會報錯
原理
內(nèi)置類型:
對于內(nèi)置類型,new/delete與malloc/free是相同的,唯一不同的是,new在申請空間失敗后會自動拋異常,而malloc要自己手動實現(xiàn)來驗證是否申請失敗
自定義類型:
new的原理其實就是operator new() + 構(gòu)造函數(shù)
先調(diào)用operator new(),再調(diào)用構(gòu)造函數(shù)
operator new()函數(shù):進行空間申請
構(gòu)造函數(shù):初始化對象
而operator new()函數(shù)其實就是由malloc()函數(shù)組成的,但和malloc()不同的是,它不需要在申請空間后要自己檢查是否申請成功,operator new()函數(shù)會自己判斷,然后根據(jù)申請成功與否來進行拋異常(在這里我們就不細講拋異常,會在后文在做詳細講解)
delete的原理是operator delete() + 析構(gòu)函數(shù)
先進行析構(gòu),再調(diào)用operator delete()
析構(gòu)函數(shù):將對象指向資源釋放
operator delete():銷毀空間
而operator delete()函數(shù)的底層就是free()函數(shù)
至于new T[N]和delete[]的原理和new/delete是一樣的,只不過要根據(jù)申請了多少個空間來進行對應(yīng)次數(shù)的構(gòu)造函數(shù)和析構(gòu)函數(shù)的調(diào)用
所以new/delete在底層其實就是malloc/free,不過是在malloc和free的基礎(chǔ)上進行了一些封裝,加了一些功能
匹配問題
在new和delete的匹配問題上,內(nèi)置類型和自定義類型是不相同的
內(nèi)置類型:
int main()
{
int* a1 = new int;//動態(tài)申請一個int類型的空間
delete a1;//釋放空間
int* a3 = new int[10];//動態(tài)申請十個int類型的空間
delete[] a3;
//delete a3;//這樣也可以進行a3的釋放,內(nèi)置類型可以考慮不加[]
return 0;
}
自定義類型:
class A
{
public:
A(int a)
{
_a1 = _a2 = a;
}
~A()
{
cout << "~A()" << endl;
}
private:
int _a1;
int _a2;
};
int main()
{
A* a1 = new A;
delete a1;
A* a2 = new A(1);
delete a2;
A* a3 = new A[10]{1,2,3};
delete[] a3;
//delete a3;//error
return 0;
}
?之所以會導(dǎo)致這樣的問題,是因為一個這樣的機制:
對于new一個自定義類型對象,在new[N]時,不僅會給對象申請一份空間,還會對[]中的N申請一塊空間,我們可以在Vs上進行驗證:
我們也可以從這個對象的大小來判斷,原本根據(jù)A這個類來判斷a3的大小應(yīng)該是80個字節(jié),而這里卻是84個字節(jié),那多出來的4個字節(jié)就是為[]中的數(shù)字開辟的空間
意義:
那有人就會有疑惑,開辟這個空間的意義在哪?
1、析構(gòu)函數(shù)調(diào)用次數(shù)
我們在前面知道new了幾個空間就需要調(diào)用幾次構(gòu)造函數(shù)和幾次析構(gòu)函數(shù),new當(dāng)然知道要調(diào)用幾次構(gòu)造函數(shù)(因為[]里面寫好了),當(dāng)時operator卻不知道要調(diào)用幾次析構(gòu)函數(shù)??!
所以就要開辟一塊空間給[]中的數(shù)字,來告訴[],然后在operator后面加上[]就可以讓operator調(diào)用正確次數(shù)的析構(gòu)函數(shù)
但這種情況下編譯器還不會報錯
2、錯誤位置釋放
在外面delete這個對象開辟的空間時,如果不加[],那我們就是從對象的地址開始釋放,而前面的空間就無法釋放,這就是最嚴(yán)重的問題:從錯誤地址開始釋放,這樣就會導(dǎo)致編譯器報錯
注:不需要匹配的情況
當(dāng)類中沒顯式實現(xiàn)析構(gòu)函數(shù)的情況下,不加[]是可以正常運行的,因為不會調(diào)用析構(gòu)函數(shù),而在這情況下,也不會給[]中數(shù)字開辟空間,會直接從對象首地址開始釋放
在這里就涉及到編譯器的優(yōu)化,因為沒有顯式實現(xiàn)析構(gòu)函數(shù),所以編譯器在不需要釋放什么資源的情況下就會優(yōu)化掉自己的生成的默認析構(gòu)函數(shù)
new/delete和malloc/free的區(qū)別
malloc/free和new/delete的共同點是:都是從堆上申請空間,并且需要用戶手動釋放。
不同的地方是:
1. malloc和free是函數(shù),new和delete是操作符
2. malloc申請的空間不會初始化,new可以初始化
3. malloc申請空間時,需要手動計算空間大小并傳遞,new只需在其后跟上空間的類型即可,如果是多個對象,[]中指定對象個數(shù)即可
4. malloc的返回值為void*, 在使用時必須強轉(zhuǎn),new不需要,因為new后跟的是空間的類型
5. malloc申請空間失敗時,返回的是NULL,因此使用時必須判空,new不需要,但是new需
要捕獲異常
6. 申請自定義類型對象時,malloc/free只會開辟空間,不會調(diào)用構(gòu)造函數(shù)與析構(gòu)函數(shù),而new在申請空間后會調(diào)用構(gòu)造函數(shù)完成對象的初始化,delete在釋放空間前會調(diào)用析構(gòu)函數(shù)完成空間中資源的清理釋放
柚子快報激活碼778899分享:【C++初階】內(nèi)存管理
本文內(nèi)容根據(jù)網(wǎng)絡(luò)資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點和立場。
轉(zhuǎn)載請注明,如有侵權(quán),聯(lián)系刪除。