C++内存管理:new/delete与内存泄漏实战

一、上期回顾

掌握函数模板、类模板、泛型编程、模板特化,理解了 STL 容器能适配任意类型的底层原因。今天攻坚C++ 内存管理,搞定 new/delete、内存分区、野指针、内存泄漏四大核心痛点。

二、C/C++ 程序内存五大分区

程序运行时内存划分为 5 块,面试必背:

  1. 栈区:局部变量、函数形参、栈对象;自动分配自动释放
  2. 堆区:new/malloc 开辟的空间;手动申请手动释放
  3. 全局 / 静态区:全局变量、static 静态变量;程序全程存在
  4. 常量区:字符串常量、const 全局常量;只读不可修改
  5. 代码区:存放二进制程序指令,只读

三、malloc/free 与 new/delete 核心区别

1. C 语言 malloc/free

  • 只分配原始内存,不调用构造、析构函数

  • 需要强转类型、手动计算字节大小

  • 不会初始化内存

    int* p = (int*)malloc(sizeof(int));
    free(p);

2. C++ new/delete

  • 分配内存 + 自动调用构造函数

  • 释放内存 + 自动调用析构函数

  • 无需计算大小、无需强转

  • 支持数组形式 new [] /delete []

    int* p = new int;
    delete p;

    // 数组开辟
    int* arr = new int[5];
    delete[] arr;

核心区别总结

  1. new 自动调用构造,malloc 只开空间
  2. new 无需强转、自动计算大小
  3. delete 自动调用析构,free 直接回收内存
  4. 数组必须配对 new[]delete[]

四、new 的三种使用形式

复制代码
// 1. 普通开辟单个变量
int* p1 = new int;

// 2. 开辟并初始化
int* p2 = new int(100);

// 3. 开辟数组
int* p3 = new int[5];

五、内存泄漏成因与规避

什么是内存泄漏

堆空间用new申请后,没有 delete 释放,程序不退出内存一直占用。

常见泄漏场景

  1. 函数内 new,没有返回也没有释放
  2. 指针重新赋值,旧地址丢失无法释放
  3. 类中堆成员,析构函数没写 delete

避坑原则

谁申请,谁释放;成对使用 new/delete


六、野指针成因与危害

野指针定义

指向非法未知内存的指针,没有有效指向。

产生原因

  1. 指针未初始化,随机地址
  2. 指针指向栈变量,变量销毁后指针悬空
  3. 内存释放后,未把指针置空

规避方法

  1. 定义指针初始化为 nullptr

  2. 释放内存后立刻置空

  3. 不访问悬空指针

    // 规范写法
    int* p = new int;
    delete p;
    p = nullptr; // 置空,避免野指针


七、内存经典错误示范

错误 1:重复释放

复制代码
int* p = new int;
delete p;
delete p;   // 崩溃,重复释放

错误 2:数组不匹配 delete []

复制代码
int* arr = new int[5];
delete arr;   // 错误,必须 delete[]

错误 3:野指针访问

复制代码
int* p;
*p = 10;  // 未初始化,野指针崩溃

八、构造析构与 new/delete 联动演示

复制代码
#include <iostream>
using namespace std;

class Test
{
public:
    Test(){cout << "构造函数调用" << endl;}
    ~Test(){cout << "析构函数调用" << endl;}
};

int main()
{
    // 栈对象:自动构造、自动析构
    Test t1;

    // 堆对象:new触发构造,delete触发析构
    Test* t2 = new Test;
    delete t2;

    return 0;
}

运行结果:

复制代码
构造函数调用
构造函数调用
析构函数调用
析构函数调用

九、今日核心总结

  1. 内存五分区:栈、堆、全局静态、常量、代码区
  2. new/delete 比 malloc/free 多了构造析构调用
  3. 数组必须严格配对 new[]delete[]
  4. 内存泄漏:new 不 delete;野指针:未初始化 / 悬空指针
  5. 开发规范:指针初始化为空、释放后置空、成对申请释放

十、课后练习

  1. 用 new 开辟单个 int 并初始化,delete 释放
  2. 尝试不 delete 观察内存泄漏逻辑
  3. 定义未初始化指针,理解野指针危害
相关推荐
星星码️1 小时前
LeetCode刷题简单篇之反转字母
c++·算法·leetcode
其实防守也摸鱼1 小时前
VS code怎么使用 Conda 安装预编译包
开发语言·网络·c++·vscode·安全·web安全·conda
默子昂1 小时前
langchain 基本使用
开发语言·python·langchain
yaoxin5211231 小时前
402. Java 文件操作基础 - 读取二进制文件
java·开发语言·python
Hello.Reader1 小时前
ds4.c 深度解析为 DeepSeek V4 Flash 打造的本地推理引擎
c语言·开发语言
naturerun1 小时前
螺旋形遍历奇数阶矩阵
c++·算法·矩阵
TopGames1 小时前
〖Unity GPU粒子插件〗ParticleSystem的终极性能优化方案 十倍百倍的显著提升 现有特效转GPU粒子 高性能特效方案
java·开发语言
Chase_______2 小时前
计算机数据存储全解:从底层进制转换到存储介质演进
java·开发语言·python
栉甜2 小时前
Js进阶(4)
开发语言·javascript·原型模式