C++ 内存分区 堆区

一、堆区是什么?

堆区是 C++ 程序运行时,由程序员手动申请、手动释放的一块动态内存区域 。它不属于任何函数,不属于任何局部作用域,生命周期完全由程序员自己控制。

  • 栈:系统自动管
  • 堆:程序员自己管
  • 全局区:程序启动就有,结束才没
  • 堆:想用就 new,不用就 delete

二、堆区的核心特点

1. 内存分配方式:动态分配

程序运行过程中随时可以申请、随时可以释放,大小可以任意指定。

2. 内存不连续

堆是链表结构 管理空闲块,多次申请的内存地址不连续。

3. 空间巨大

栈只有几 MB,堆可以用到 几 GB(受操作系统限制)。

4. 分配速度比栈慢

因为需要遍历空闲链表、分配、标记、防止碎片。

5. 生命周期由程序员控制

  • new → 分配
  • delete → 释放
  • 不释放 → 内存泄漏
  • 释放后再用 → 野指针、崩溃

6. 多线程共享

同一个进程内的所有线程,共享同一个堆空间。


三、堆区用来存什么?

  1. 动态大小的数组(运行时才知道大小)
  2. 大对象(太大栈放不下)
  3. 需要跨函数、跨作用域使用的对象
  4. 容器底层(vector、string、map 全在堆上)

四、堆区的使用方式(C++ 标准)

1. 申请单个变量

cpp

运行

复制代码
int* p = new int(100);  // 堆上分配 int,值=100

2. 申请数组

cpp

运行

复制代码
int* arr = new int[10]; // 堆上分配 10 个 int 的数组

3. 释放内存

cpp

运行

复制代码
delete p;       // 释放单个变量
delete[] arr;   // 释放数组 必须加[]

4. 最规范写法

cpp

运行

复制代码
int* p = new int(20);
delete p;
p = nullptr;  // 释放后置空,避免野指针

五、堆区底层原理(非常重要)

1. 堆内存如何分配?

操作系统维护一个 空闲内存链表

  • new → 遍历链表找一块足够大的内存
  • 标记为已使用
  • 返回地址给程序

2. 堆内存增长方向

从低地址 → 高地址(和栈相反)

3. 堆内存不会自动释放

只有两种情况会释放:

  1. 程序员 delete
  2. 程序结束,OS 回收

六、堆区常见错误(90% 的人都踩过)

1. 内存泄漏(最常见)

cpp

运行

复制代码
void func() {
    int* p = new int(10);
} // 函数结束,p 销毁,但堆内存还在!泄漏了

2. 重复释放

cpp

运行

复制代码
int* p = new int;
delete p;
delete p; // 崩溃!重复释放堆内存

3. 释放后继续使用(野指针)

cpp

运行

复制代码
int* p = new int(10);
delete p;
*p = 20; // 严重错误!访问已释放的堆内存

4. new /delete 不匹配

cpp

运行

复制代码
int* arr = new int[10];
delete arr; // 错误!应该用 delete[]

5. 不初始化就使用

cpp

运行

复制代码
int* p = new int; // 未初始化,值是随机垃圾数

七、堆 vs 栈(最清晰对比)

表格

特点 栈区(stack) 堆区(heap)
谁管理 系统自动分配、自动释放 程序员手动 new/delete
速度 极快 较慢
空间 小(MB 级别) 大(GB 级别)
连续性 连续内存 不连续
生命周期 函数结束即销毁 手动控制
碎片 无碎片 容易产生内存碎片
方向 高地址 → 低地址 低地址 → 高地址
报错 栈溢出 内存不足、野指针、重复释放

八、堆区使用规范(企业级标准)

  1. 谁申请,谁释放
  2. new 必须配对 delete,new[] 配对 delete[]
  3. 释放后指针立刻置空 nullptr
  4. 不要返回栈指针,但可以返回堆指针
  5. 能用栈就不用堆,堆更耗性能
  6. 现代 C++ 尽量用 智能指针(unique_ptr/shared_ptr) 自动管理堆内存,避免泄漏
相关推荐
大猫和小黄2 小时前
深入理解 Java Optional:从设计哲学到工程实战
java
数据库百宝箱2 小时前
rum&gin索引对比
java·数据库·gin
2601_962218612 小时前
C语言中三种库的编译和使用方法
开发语言·c++
传奇开心果编程2 小时前
中庸、有容、破执:仓颉编程语言的中华智慧结晶——三重哲学境界思辨
开发语言·华为·开源·软件工程
yychen_java2 小时前
第六篇:Spring AI 实战:将 Java 业务接口封装成企业级 MCP Server
java·人工智能·spring
jimy12 小时前
派生类重写基类虚函数(二):override的作用
开发语言·c++
_upupup3 小时前
异常(C++)
java·开发语言·jvm
ebiobiz3 小时前
基于 GD32 Embedded Builder (GEB) 与 Nimmake 的 MCU 工程搭建指南
c++·python·单片机·嵌入式硬件·mcu
g10565591393 小时前
公有云_云运维服务
java·运维·服务器
hetao17338373 小时前
2026-09-29 hetao1733837 的刷题记录
c++·算法