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. 定义未初始化指针,理解野指针危害
相关推荐
众少成多积小致巨6 小时前
JNI (Java Native Interface) 技术手册中文参考指南
android·java·c++
clint4564 天前
C++进阶(1)——前景提要
c++
夜悊4 天前
C++代码示例:进制数简单生成工具
c++
郝学胜_神的一滴5 天前
CMake 021: IF 条件判据详诠
c++·cmake
_wyt0015 天前
洛谷 B3930 [GESP202312 五级] 烹饪问题 题解
c++·gesp
LDR0065 天前
Type-C 快充全面升级!LDR6601 赋能个人护理便携电机,重塑剃须刀 / 理发器新体验
c语言·开发语言
雪碧聊技术5 天前
Tree.js是什么?一文讲透
开发语言·javascript·ecmascript
码云数智-园园5 天前
C++20 Modules 模块详解
java·开发语言·spring
swordbob5 天前
NIO的channel中什么是 fd(File Descriptor,文件描述符)
java·开发语言·nio
源分享5 天前
Java线程同步的多种实现方法(非常详细)
java·开发语言·jvm