【C++小白逆襲】內存管理從崩潰到精通的秘籍

目錄

  • 【C++小白逆襲】內存管理從崩潰到精通的秘籍
    • 前言:為什么內存管理讓我掉了N根頭發?
    • 內存四區大揭秘:你的變量都住在哪里?🏠
      • 內存就像大學宿舍區 🏘?
    • C語言的內存管理:手動搬磚時代 🧱
      • 舉個栗子 🌰
    • C++的內存管理:智能建房時代 🏗?
      • 內置類型:簡單裝修 🔨
      • 自定義類型:豪華裝修 🏰
    • new和delete的底層魔法 🧙?♂?
      • 簡單說就是:
    • 內存管理避坑指南 🚫💣
      • 1. 匹配使用!匹配使用!匹配使用!
      • 2. 別做"渣男"!申請了就要釋放
      • 3. 野指針是"幽靈",小心被附身
    • malloc/free vs new/delete:終極對決 🆚
    • 開篇答案揭曉 🎉
    • 總結:內存管理三板斧 🪓
      • 定位new:在已有的空間上"蓋房子" 🏗?
    • operator new/delete的底層真相 🕵??♂?
    • 內存管理常見面試題 🤔
      • 1. malloc/calloc/realloc的區別?
      • 2. new和malloc的根本區別?
      • 3. 內存泄漏有哪些危害?
    • 最后的叮囑 💌
      • 💻 定位new代碼運行效果演示
    • 最后的最后... 🎁

在這里插入圖片描述
🌟個人主頁 :L_autinue_Star
?
🌟當前專欄:c++進階


【C++小白逆襲】內存管理從崩潰到精通的秘籍

前言:為什么內存管理讓我掉了N根頭發?

剛學C++的時候,我總覺得內存管理是只"紙老虎"——直到第一次寫出內存泄漏的代碼,看著任務管理器里飆升的內存占用,我才明白這玩意兒有多"咬人"!😭 今天就用大學生視角,把內存管理掰開揉碎講清楚,讓你少走我踩過的坑~

內存四區大揭秘:你的變量都住在哪里?🏠

先看段代碼猜謎游戲(敢不敢不看答案先做題?):

int globalVar = 1;                  // 全局變量
static int staticGlobalVar = 1;     // 靜態全局變量
void Test() {static int staticVar = 1;       // 靜態局部變量int localVar = 1;               // 局部變量int num1[10] = {1,2,3,4};       // 數組char char2[] = "abcd";          // 字符數組const char* pChar3 = "abcd";    // 字符串常量指針int* ptr1 = (int*)malloc(sizeof(int)*4); // 動態內存
}

靈魂拷問:這些變量都住在哪里?(答案在文末揭秘)

內存就像大學宿舍區 🏘?

其實內存分布就像我們的校園:

  • 代碼段:相當于教學樓,存放可執行代碼和常量(只讀不修改)
  • 數據段:類似教師公寓,住著全局變量和靜態變量(程序運行期間一直存在)
  • 棧區:好比臨時自習室,局部變量/函數參數在這里(自動分配釋放)
  • 堆區:就像校外出租房,需要自己找房(申請)和退租(釋放)

在這里插入圖片描述

💡 學霸筆記:棧是向下增長的(地址越來越小),堆是向上增長的(地址越來越大),就像兩個方向相反的電梯!

C語言的內存管理:手動搬磚時代 🧱

C語言用四個函數管理內存,我稱之為"內存F4":

  • malloc:申請空間(只給錢不裝修)
  • calloc:申請空間并初始化為0(給錢+簡單裝修)
  • realloc:調整空間大小(換更大/小的房子)
  • free:釋放空間(退租)

舉個栗子 🌰

void Test() {// malloc: 申請4個int大小空間(16字節)int* p1 = (int*)malloc(sizeof(int)*4);// calloc: 申請4個int并初始化為0(比malloc多一步清零)int* p2 = (int*)calloc(4, sizeof(int));// realloc: 把p2的空間擴大到10個int(可能搬家哦!)int* p3 = (int*)realloc(p2, sizeof(int)*10);// 注意:realloc成功后p2可能失效,直接用p3就好啦!free(p3); // 一定要釋放!不然房子就一直占著~
}

?? 踩坑警告:realloc如果擴容失敗會返回NULL,直接賦值可能丟失原指針!正確姿勢是先用臨時變量接收~

C++的內存管理:智能建房時代 🏗?

C++覺得C語言太麻煩,于是發明了newdelete這對"智能管家",不僅幫你找房,還負責裝修(調用構造函數)和打掃(調用析構函數)!

內置類型:簡單裝修 🔨

void Test() {// 申請單個int(毛坯房)int* ptr4 = new int;// 申請int并初始化為10(簡裝房)int* ptr5 = new int(10);// 申請3個int數組(聯排別墅)int* ptr6 = new int[3];// 記得匹配釋放哦!delete ptr4;       // 拆單個房子delete ptr5;       // 拆簡裝房delete[] ptr6;     // 拆聯排別墅([]不能忘!)
}

在這里插入圖片描述

自定義類型:豪華裝修 🏰

對于我們自己定義的類,newdelete會自動調用構造和析構函數,這可是C語言做不到的!

class A {
public:A(int a=0) : _a(a) { cout << "A():我出生啦!" << this << endl; }~A() { cout << "~A():我走啦!" << this << endl; }
private:int _a;
};int main() {A* p1 = (A*)malloc(sizeof(A)); // C語言方式:只建房子不裝修A* p2 = new A(1);              // C++方式:建房子+裝修(調用構造)free(p1);  // C語言方式:只拆房子不打掃delete p2; // C++方式:打掃衛生+拆房子(調用析構)return 0;
}

? 神奇時刻:運行這段代碼,你會看到new創建的對象會打招呼,delete時會說再見,而malloc/free的對象啥也不說!

new和delete的底層魔法 🧙?♂?

你以為new是直接變出空間的?其實它背后有兩個"幫手":

  • operator new:負責申請空間(底層還是用malloc)
  • operator delete:負責釋放空間(底層還是用free)

簡單說就是:

new = operator new(申請空間) + 構造函數(初始化)
delete = 析構函數(清理) + operator delete(釋放空間)

當申請失敗時,malloc返回NULL,而new會拋出異常,所以C++不需要像C語言那樣判空,而是用try-catch捕獲異常~

內存管理避坑指南 🚫💣

1. 匹配使用!匹配使用!匹配使用!

重要的事情說三遍:

  • mallocfree
  • newdelete
  • new[]delete[](數組一定要加[]!)

2. 別做"渣男"!申請了就要釋放

內存泄漏就像借了東西不還,次數多了系統就被"掏空"!😭

// 反面教材(千萬別學!)
void badCode() {int* p = new int[100];// 忘記delete p; → 內存泄漏!
}

3. 野指針是"幽靈",小心被附身

釋放后記得把指針置為NULL,不然就變成指向"墳場"的野指針:

int* p = new int;
delete p;
p = NULL; // 重要!避免野指針

malloc/free vs new/delete:終極對決 🆚

特性malloc/freenew/delete
身份函數操作符
初始化不初始化可初始化
返回值void*(需強轉)直接返回對應類型
錯誤處理返回NULL拋異常
自定義類型只開空間開空間+構造/析構

開篇答案揭曉 🎉

還記得開頭的變量都住在哪里嗎?答案來啦:

  • globalVar → 數據段
  • staticGlobalVar → 數據段
  • staticVar → 數據段
  • localVar → 棧區
  • num1 → 棧區
  • char2 → 棧區(數組本身)
  • *char2 → 棧區(數組內容)
  • pChar3 → 棧區(指針本身)
  • *pChar3 → 代碼段(字符串常量)
  • ptr1 → 棧區(指針本身)
  • *ptr1 → 堆區(指向的內容)

總結:內存管理三板斧 🪓

  1. 懂分區:知道變量住哪個"宿舍"
  2. 會申請:malloc/free是C爺爺,new/delete是C++管家
  3. 記得還:用完內存一定要釋放,做個有始有終的好孩子!

希望這篇文章能幫你搞定內存管理!如果有收獲,別忘了點贊收藏~ 有問題歡迎評論區交流,一起在C++的世界里打怪升級!🚀## 進階內容:內存池與定位new 🏊?♂?

當你需要頻繁創建和銷毀對象時(比如游戲中的子彈),頻繁使用new/delete會導致內存碎片。這時候內存池就派上用場了——提前申請一大塊內存,然后用定位new在上面創建對象,就像在游泳池里分配泳道一樣高效!

定位new:在已有的空間上"蓋房子" 🏗?

class A {
public:A(int a=0) : _a(a) { cout << "A():我出生在指定地址!" << this << endl; }
private:int _a;
};int main() {// 1. 先申請一塊與A對象大小相同的"空地"A* p = (A*)malloc(sizeof(A));// 2. 用定位new在這塊空地上"蓋房子"(調用構造函數)new(p)A(10); // 注意語法:new(地址)類型(參數)// 3. 手動調用析構函數(因為delete不會自動調用)p->~A();// 4. 釋放原始內存free(p);return 0;
}

🧠 學霸思考:定位new就像二手房裝修——房子(內存)是現成的,但需要重新裝修(調用構造函數)才能入住!

operator new/delete的底層真相 🕵??♂?

你可能好奇:new到底怎么申請內存的?其實它偷偷調用了operator new函數,相當于"裝修公司"外包給"建筑隊":

// operator new的簡化實現
void* operator new(size_t size) {void* p = malloc(size); // 實際還是用malloc申請空間if (p == NULL) {throw bad_alloc(); // 申請失敗拋異常(區別于malloc返回NULL)}return p;
}// operator delete的簡化實現
void operator delete(void* p) {free(p); // 底層調用free釋放空間
}

所以new和delete的工作流程是:

  1. new → operator new(申請空間) → 構造函數(初始化)
  2. delete → 析構函數(清理) → operator delete(釋放空間)

內存管理常見面試題 🤔

1. malloc/calloc/realloc的區別?

  • malloc:只申請空間,不初始化
  • calloc:申請空間并初始化為0(適合數組)
  • realloc:調整已申請的空間大小(可能搬家)

2. new和malloc的根本區別?

最核心的區別是對自定義類型的處理:new會調用構造函數,delete會調用析構函數,而malloc/free不會!

3. 內存泄漏有哪些危害?

短期程序(如命令行工具)可能看不出影響,但長期運行的程序(如服務器)會越來越慢,最終崩潰!就像房間垃圾不清理,越堆越多直到無法住人~

最后的叮囑 💌

內存管理就像理財——合理分配資源(內存),及時回收(釋放),才能避免"破產"(程序崩潰)。剛開始可能會犯錯,但多寫多練,你也能成為內存管理大師!

如果這篇文章幫你理清了內存管理的思路,記得點贊收藏哦~ 有任何問題,歡迎在評論區留言,我們一起進步!🎉### 📝 內存管理自查清單(避坑必備)

常見錯誤解決方法嚴重程度
malloc后未判空if(p == NULL) { 處理錯誤 }???
new[] 搭配 delete(漏寫[])嚴格使用 delete[] 釋放數組????
重復釋放同一塊內存釋放后指針置為 NULL???
內存泄漏使用智能指針(后續文章講解)?????
野指針指針初始化/釋放后置為 NULL????

💻 定位new代碼運行效果演示

如果運行定位new的示例代碼,你會看到這樣的輸出:

A():我出生在指定地址!0x7f8a9b4052a0
~A():我走啦!0x7f8a9b4052a0

這證明定位new確實調用了構造函數,而手動調用p->~A()觸發了析構函數~


最后的最后… 🎁

內存管理是C++的核心難點,也是面試官的"心頭好"。剛開始寫崩程序很正常,我曾經因為內存泄漏調試到凌晨三點(說多了都是淚😭)。但只要記住"申請了就釋放,匹配使用工具"的原則,你一定能攻克這個難關!

如果這篇文章對你有幫助,別忘了點贊+收藏,也歡迎分享給正在學C++的小伙伴~ 關注我,后續還會更新智能指針、內存池等進階內容哦!🚀

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/88618.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/88618.shtml
英文地址,請注明出處:http://en.pswp.cn/web/88618.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【網絡安全】利用 Cookie Sandwich 竊取 HttpOnly Cookie

未經許可,不得轉載。 文章目錄 引言Cookie 三明治原理解析Apache Tomcat 行為Python 框架行為竊取 HttpOnly 的 PHPSESSID Cookie第一步:識別 XSS 漏洞第二步:發現反射型 Cookie 參數第三步:通過 Cookie 降級實現信息泄露第四步:整合攻擊流程修復建議引言 本文將介紹一種…

【工具】什么軟件識別重復數字?

網上的數字統計工具雖多&#xff0c;但處理重復數字時總有點不盡如人意。 要么只能按指定格式輸入&#xff0c;要么重時得手動一點點篩&#xff0c;遇上數據量多的情況&#xff0c;光是找出重復的數字就得另外花不少功夫。? 于是我做了個重復數字統計器&#xff0c;不管是零…

CSS分層渲染與微前端2.0:解鎖前端性能優化的新維度

CSS分層渲染與微前端2.0&#xff1a;解鎖前端性能優化的新維度 當你的頁面加載時間超過3秒&#xff0c;用戶的跳出率可能飆升40%以上。這并非危言聳聽&#xff0c;而是殘酷的現實。在當前前端應用日益復雜、功能日益臃腫的“新常態”下&#xff0c;性能優化早已不是錦上添花的“…

AI Agent開發學習系列 - langchain之Chains的使用(5):Transformation

Transformation&#xff08;轉換鏈&#xff09;是 LangChain 中用于“自定義數據處理”的鏈式工具&#xff0c;允許你在鏈路中插入任意 Python 代碼&#xff0c;對輸入或中間結果進行靈活處理。常用于&#xff1a; 對輸入/輸出做格式化、過濾、摘要、拆分等自定義操作作為 LLMC…

Druid 連接池使用詳解

Druid 連接池使用詳解 一、Druid 核心優勢與架構 1. Druid 核心特性 特性說明價值監控統計內置 SQL 監控/防火墻實時查看 SQL 執行情況防 SQL 注入WallFilter 防御機制提升系統安全性加密支持數據庫密碼加密存儲符合安全審計要求擴展性強Filter 鏈式架構自定義功能擴展高性能…

9.2 埃爾米特矩陣和酉矩陣

一、復向量的長度 本節的主要內容可概括為&#xff1a;當對一個復向量 z\pmb zz 或復矩陣 A\pmb AA 轉置后&#xff0c;還要取復共軛。 不能在 zTz^TzT 或 ATA^TAT 時就停下來&#xff0c;還要對所有的虛部取相反的符號。對于一個分量為 zjajibjz_ja_jib_jzj?aj?ibj? 的列向…

AI驅動的低代碼革命:解構與重塑開發范式

引言&#xff1a;低代碼平臺的范式轉移 當AI技術與低代碼平臺深度融合&#xff0c;軟件開發正經歷從"可視化編程"到"意圖驅動開發"的根本性轉變。這種變革不僅提升了開發效率&#xff0c;更重新定義了人與系統的交互方式。本文將從AI介入的解構層次、交互范…

zookeeper etcd區別

ZooKeeper與etcd的核心區別體現在設計理念、數據模型、一致性協議及適用場景等方面。?ZooKeeper基于ZAB協議實現分布式協調&#xff0c;采用樹形數據結構和臨時節點特性&#xff0c;適合傳統分布式系統&#xff1b;而etcd基于Raft協議&#xff0c;以高性能鍵值對存儲為核心&am…

模擬注意力:少量參數放大 Attention 表征能力

論文標題 SAS: Simulated Attention Score 論文地址 https://arxiv.org/pdf/2507.07694 代碼 見論文附錄 作者背景 摩根士丹利&#xff0c;斯坦福大學&#xff0c;微軟研究院&#xff0c;新加坡國立大學&#xff0c;得克薩斯大學奧斯汀分校&#xff0c;香港大學 動機 …

零基礎|寶塔面板|frp內網穿透|esp32cam遠程訪問|微信小程序

1.準備好阿里云服務器和寶塔面板2.安裝frp服務端3.測試(密碼賬號在詳情里面)4.配置客戶端#一、沒有域名情況下 [common] server_addr #公網ip地址&#xff0c;vps server_port 7000 服務的bind_port token 12121212 [httpname] type tcp # 沒有域名情況下使用 tcp local_i…

Spring Boot整合MyBatis+MySQL+Redis單表CRUD教程

Spring Boot整合MyBatisMySQLRedis單表CRUD教程 環境準備 1. Redis安裝&#xff08;Windows&#xff09; # 下載Redis for Windows # 訪問: https://github.com/tporadowski/redis/releases # 下載Redis-x64-5.0.14.1.msi并安裝# 啟動Redis服務 redis-server# 測試連接 redis-c…

linux學習第30天(線程同步和鎖)

線程同步協同步調&#xff0c;對公共區域數據按序訪問。防止數據混亂&#xff0c;產生與時間有關的錯誤。數據混亂的原因資源共享(獨享資源則不會)調度隨機(意味著數據訪問會出現競爭)線程間缺乏必要同步機制鎖的使用建議鎖&#xff01;對公共數據進行保護。所有線程【應該】在…

JavaScript中的系統對話框:alert、confirm、prompt

JavaScript中的系統對話框&#xff1a;alert、confirm、prompt 在Web開發的世界里&#xff0c;JavaScript始終扮演著“橋梁”的角色——它連接用戶與網頁&#xff0c;讓靜態的頁面煥發活力。而在這座橋梁上&#xff0c;系統對話框&#xff08;System Dialogs&#xff09;是最基…

圓冪定理深度探究——奧數專題講義

圓冪定理深度探究——奧數專題講義 開篇語&#xff1a;幾何中的"隱藏等式" 在平面幾何的星空中&#xff0c;圓與直線的交點仿佛散落的珍珠&#xff0c;而連接這些珍珠的線段之間&#xff0c;藏著一組令人驚嘆的等量關系。當我們用直尺測量、用邏輯推導時&#xff0c;…

一文看懂顯示接口:HDMI / DP / VGA / USB-C 有什么區別?怎么選?

剛買的新顯示器&#xff0c;插上線卻發現畫面糊成馬賽克&#xff1f;游戲打到關鍵時刻突然黑屏&#xff1f;4K電影看著看著就卡頓&#xff1f;別急&#xff01;這些問題很可能都是"接口沒選對"惹的禍&#xff01;今天我們就來徹底搞懂HDMI、DP、VGA、USB-C這些常見的…

【ARM嵌入式匯編基礎】- 操作系統基礎(二)

操作系統基礎(二) 文章目錄 操作系統基礎(二)6、線程7、進程內存管理8、內存頁9、內存保護10、匿名內存和內存映射內存11、內存映射文件和模塊6、線程 程序首次啟動時,會創建一個新進程,并為該程序分配一個線程。該初始線程負責初始化進程并最終調用程序中的主函數。多線…

C#調用Matlab生成的DLL

C#調用Matlab生成的DLL 1.Matlab生成DLL文件1.1準備腳本文件1.2.輸出DLL文件2.Winform項目中調用DLL2.1.創建Winform項目2.2.添加引用2.3.調用DLL2.3.1. 方法12.3.2. 方法22.4.配置CPU3.運行測試4.缺點1.Matlab生成DLL文件 1.1準備腳本文件 在Matlab環境下創建腳本文件calcul…

Julia爬取數據能力及應用場景

Julia 是一種高性能編程語言&#xff0c;特別適合數值計算和數據分析。然而&#xff0c;關于數據爬取&#xff08;即網絡爬蟲&#xff09;方面&#xff0c;我們需要明確以下幾點&#xff1a;雖然它是一門通用編程語言&#xff0c;但它的強項不在于網絡爬取&#xff08;Web Scra…

Java03 二維數組|方法

一、聲明數組和初始化&#xff08;掌握&#xff09;數據類型[] 數組名 ; 數據類型 數組名[] ;靜態初始化數據類型[] 數組名 {元素1,元素2,元素3};動態初始化數據類型[] 數組名 new 數據類型[5]; 數組名[0] 元素1;二、數組的內存結構&#xff08;掌握&#xff09;package…

1. JVM介紹和運行流程

1. jvm是什么JVM&#xff08;Java Virtual Machine&#xff09;是 Java 程序的運行環境&#xff0c;它是 Java 技術的核心組成部分&#xff0c;負責執行編譯后的 Java 字節碼&#xff08;.class文件&#xff09;。jvm 說白了就是虛擬機&#xff0c;一個專門運行java字節碼文件的…