C++ new與malloc和delete及free動(dòng)態(tài)內(nèi)存管理及區(qū)別介紹
一般情況-堆上申請(qǐng)普通變量空間
申請(qǐng)堆空間時(shí),實(shí)驗(yàn)表明 new/malloc 與 delete/free 是可以混用的,即可以通過free()釋放掉new出來的一塊內(nèi)存。
int main() {
int *p = new int(123);
delete p;
//free(p);
}特殊情況-堆上申請(qǐng)對(duì)象空間
class Person{
public:
Person(){
cout << "construct call ......" << endl;
}
~Person(){
cout << "destruct call ......" << endl;
}
private:
int m_age;
};
int main() {
Person *ptr = new Person();
if (ptr != nullptr)
{
free(ptr);
}
return 0;
}單步走看內(nèi)存分布圖:

可以看到,執(zhí)行完free(ptr) 后,內(nèi)存確實(shí)是被釋放了。(補(bǔ)充一下:fd作為開始結(jié)束的標(biāo)志,"cd cd cd cd"代表開辟的內(nèi)存,四個(gè)字節(jié))
但是!對(duì)于一個(gè)對(duì)象而言,new和delete關(guān)鍵字還額外做了 調(diào)用構(gòu)造函數(shù)和調(diào)用析構(gòu)函數(shù)這兩個(gè)步驟。

可以看到,程序只調(diào)用了構(gòu)造函數(shù)(new關(guān)鍵字產(chǎn)生),但是由于使用的是free(),因此并沒有調(diào)用類中的析構(gòu)函數(shù)。
一般情況-堆上申請(qǐng)普通數(shù)組空間
int main() {
int *ptr = new int[10];
delete[]ptr;
//delete ptr;
return 0;
}我們知道,用new在堆上申請(qǐng)數(shù)組空間,一般delete的時(shí)候都需要加上[ ] ,即 delete[ ] 。

但實(shí)驗(yàn)表明,如果不涉及到類對(duì)象,不加[ ]也同樣可以實(shí)現(xiàn)空間的釋放,加不加[ ]是沒有區(qū)別的。
特殊情況-堆上申請(qǐng)對(duì)象數(shù)組空間
int main() {
Person *ptr = new Person[10];
delete ptr;
return 0;
}當(dāng)new一個(gè)對(duì)象數(shù)組時(shí),如果沒有用delete[ ] ,會(huì)發(fā)生崩潰報(bào)錯(cuò):

修改成delete [ ] ptr后,程序正常運(yùn)行,并調(diào)用了十次構(gòu)造函數(shù)和十次析構(gòu)函數(shù):

進(jìn)一步探索:為什么修改為delete [ ] 就會(huì)調(diào)用十次析構(gòu)函數(shù)?它是如何知道創(chuàng)建了十個(gè)對(duì)象就一定會(huì)析構(gòu)十個(gè)對(duì)象?
查看一下此種情況下的內(nèi)存分布:

可以看到我們申請(qǐng)的堆對(duì)象數(shù)組空間(10個(gè)),仔細(xì)查看改起始地址的前一個(gè)地址,按道理這并不屬于我們分配的空間,為什么會(huì)多一個(gè)地址?
0x011E4EC8 ,該地址保存的值顯示為16進(jìn)制,轉(zhuǎn)換為十進(jìn)制剛好為10(0a 00 00 00)。這個(gè)10代表著什么?
不妨修改一下這個(gè)地址,0a 00 00 00 修改成 07 00 00 00 后接著單步走:

此時(shí)原來的十個(gè)地址空間的確是完整的被釋放了,但是析構(gòu)函數(shù)只被調(diào)用了 7次!正好是自己修改的那個(gè)內(nèi)存地址的值。
到這里可以得出結(jié)論: 編譯器是如何記錄new 創(chuàng)建出來數(shù)組對(duì)象的個(gè)數(shù), 就是簡單的在創(chuàng)建空間的前一個(gè)地址,記錄了創(chuàng)建對(duì)象的個(gè)數(shù),析構(gòu)的時(shí)候就按照這個(gè)地址的值進(jìn)行析構(gòu)。
總結(jié)
1. 申請(qǐng)一個(gè)堆上的對(duì)象時(shí),不允許混搭new/delete 必須搭配使用。
2. new [ ] 和 delete [ ] 一定要配套使用,特別是申請(qǐng)對(duì)象數(shù)組時(shí)。
3. vs編譯器會(huì)在new [ ] 申請(qǐng)對(duì)象數(shù)組時(shí),在堆開始的前4個(gè)字節(jié)寫入當(dāng)前數(shù)組的長度,用于記錄delete [ ]釋放時(shí)候的析構(gòu)函數(shù)調(diào)用。
到此這篇關(guān)于C++ new與malloc和delete及free動(dòng)態(tài)內(nèi)存管理及區(qū)別介紹的文章就介紹到這了,更多相關(guān)C++動(dòng)態(tài)內(nèi)存管理內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C語言中動(dòng)態(tài)內(nèi)存管理初學(xué)者容易犯的6個(gè)錯(cuò)誤分享
本篇文章主要介紹了初學(xué)者使用C語言中動(dòng)態(tài)內(nèi)存管理的4個(gè)函數(shù)時(shí)最容易犯的6個(gè)錯(cuò)誤,以及如何避免這些錯(cuò)誤,文中的示例代碼講解詳細(xì),感興趣的可以了解一下2023-04-04
詳解C語言中g(shù)etgid()函數(shù)和getegid()函數(shù)的區(qū)別
這篇文章主要介紹了詳解C語言中g(shù)etgid()函數(shù)和getegid()函數(shù)的區(qū)別,注意getegid只返回有效的組識(shí)別碼,需要的朋友可以參考下2015-08-08
C/C++實(shí)現(xiàn)動(dòng)態(tài)庫動(dòng)態(tài)加載
在很多項(xiàng)目中,我們多少會(huì)用到第三方動(dòng)態(tài)庫,這些動(dòng)態(tài)庫一般都是相對(duì)固定,使用也很簡單,下面我們就來看看c/c++中如何實(shí)現(xiàn)動(dòng)態(tài)庫動(dòng)態(tài)加載吧2024-01-01
C語言超詳細(xì)講解結(jié)構(gòu)體與聯(lián)合體的使用
結(jié)構(gòu)體和聯(lián)合體用于描述事物的屬性,如一只鳥的信息,可能包括它的品種,體重,顏色,年齡等,接下來大家一起來詳細(xì)看看吧2022-05-05

