日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學無先后,達者為師

網站首頁 編程語言 正文

C++?new與malloc和delete及free動態內存管理及區別介紹_C 語言

作者:Huuaaaaa ? 更新時間: 2023-01-19 編程語言

一般情況-堆上申請普通變量空間

申請堆空間時,實驗表明 new/malloc 與 delete/free 是可以混用的,即可以通過free()釋放掉new出來的一塊內存。

int main() {
	int *p = new int(123);
	delete p;
	//free(p);
}

特殊情況-堆上申請對象空間

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;
}

單步走看內存分布圖:

可以看到,執行完free(ptr) 后,內存確實是被釋放了。(補充一下:fd作為開始結束的標志,"cd cd cd cd"代表開辟的內存,四個字節)

但是!對于一個對象而言,new和delete關鍵字還額外做了 調用構造函數和調用析構函數這兩個步驟。

可以看到,程序只調用了構造函數(new關鍵字產生),但是由于使用的是free(),因此并沒有調用類中的析構函數。

一般情況-堆上申請普通數組空間

int main() {
	int *ptr = new int[10];
	delete[]ptr;
	//delete ptr;
	return 0;
}

我們知道,用new在堆上申請數組空間,一般delete的時候都需要加上[ ] ,即 delete[ ] 。

但實驗表明,如果不涉及到類對象,不加[ ]也同樣可以實現空間的釋放,加不加[ ]是沒有區別的。

特殊情況-堆上申請對象數組空間

int main() {
	Person *ptr = new Person[10];
	delete ptr;
	return 0;
}

當new一個對象數組時,如果沒有用delete[ ] ,會發生崩潰報錯:

修改成delete [ ] ptr后,程序正常運行,并調用了十次構造函數和十次析構函數:

進一步探索:為什么修改為delete [ ] 就會調用十次析構函數?它是如何知道創建了十個對象就一定會析構十個對象?

查看一下此種情況下的內存分布:

可以看到我們申請的堆對象數組空間(10個),仔細查看改起始地址的前一個地址,按道理這并不屬于我們分配的空間,為什么會多一個地址?

0x011E4EC8 ,該地址保存的值顯示為16進制,轉換為十進制剛好為10(0a 00 00 00)。這個10代表著什么?

不妨修改一下這個地址,0a 00 00 00 修改成 07 00 00 00 后接著單步走:

此時原來的十個地址空間的確是完整的被釋放了,但是析構函數只被調用了 7次!正好是自己修改的那個內存地址的值。

到這里可以得出結論: 編譯器是如何記錄new 創建出來數組對象的個數, 就是簡單的在創建空間的前一個地址,記錄了創建對象的個數,析構的時候就按照這個地址的值進行析構。

總結

1. 申請一個堆上的對象時,不允許混搭new/delete 必須搭配使用。

2. new [ ] 和 delete [ ] 一定要配套使用,特別是申請對象數組時。

3. vs編譯器會在new [ ] 申請對象數組時,在堆開始的前4個字節寫入當前數組的長度,用于記錄delete [ ]釋放時候的析構函數調用。

原文鏈接:https://blog.csdn.net/Huuaaaaa/article/details/128264939

欄目分類
最近更新