網站首頁 編程語言 正文
一般情況-堆上申請普通變量空間
申請堆空間時,實驗表明 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
相關推薦
- 2022-04-19 C語言內存管理及初始化細節示例詳解_C 語言
- 2022-09-12 超實用的Nginx常見配置合集分享_nginx
- 2023-02-09 Python關鍵字?asynico基本用法_python
- 2022-12-09 python中為main方法傳參問題_python
- 2022-05-17 Spring Cloud OpenFeign源碼解析
- 2023-07-26 TypeScript中的類型聲明declare
- 2022-06-30 基于Python使用永中文檔轉換服務的方式_python
- 2022-07-10 詳解HashSet并發修改異常
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支