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) 自动管理堆内存,避免泄漏
相关推荐
金銀銅鐵6 小时前
带您看懂字节码指令(二):空循环里有什么
java·后端·ai编程
§ꦿCFོ༉6 小时前
嵌入式八股文—C语言入门学习(四)
c语言·开发语言·学习
投图匠7 小时前
十种不同风格的 CTP接口 框架
开发语言·python
吴名氏.7 小时前
Java转AI Agent教程(第十三周)混合检索与重排
java·数据库·人工智能·ai·ai agent
.痞老板.8 小时前
java ee--多线程(进阶)
java·java-ee
深入云栈10 小时前
Netty 4.2.x 源码深度解析 (二十三):ByteBuf 核心设计 —— 索引、类型与零拷贝
java·后端·架构
爱笑的k1110 小时前
nano-vllm 源码剖析:千行 Python 手写离线推理引擎的调度、显存与并行时序
开发语言·python·vllm
wang_shu_mo_ran11 小时前
MyBatis 从入门到进阶(一)
java·spring·mybatis
X1A0RAN11 小时前
PPT 图片批量处理教程:导出全部幻灯片 · 提取全部素材
开发语言·javascript·powerpoint
量化分析码农12 小时前
股票历史数据的复权参数对照:多级别返回的字段与数值差异
java·javascript·后端