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 必须配对 deletenew[] 配对 delete[]
  3. 释放后指针立刻置空 nullptr
  4. 不要返回栈指针,但可以返回堆指针
  5. 能用栈就不用堆,堆更耗性能
  6. 现代 C++ 尽量用 智能指针(unique_ptr/shared_ptr) 自动管理堆内存,避免泄漏
相关推荐
珍珠先生4 分钟前
P16 · IDEA 启动报错:找不到或无法加载主类
java
子非鱼a6 分钟前
【WEB】[RoarCTF 2019]Easy Java
java·开发语言
西峰u7 分钟前
电商项目测试报告
java·项目测试报告
软件黑马王子11 分钟前
19.资源加载模块:主要作用和基本原理
开发语言·前端框架·c#
lemon_sjdk16 分钟前
各种Binding(1)
java·javafx·绑定·源码解析
李少兄20 分钟前
记一次 IDEA 打开 Vue 项目后目录“闪现即消失“ 问题排查
java·vue.js·intellij-idea
Wang's Blog23 分钟前
Java框架快速入门: Spring Security+OAuth2之安全配置基础及函数式风格对比
java·安全·spring
小荷才露尖尖角,早有蜻蜓立上头24 分钟前
class java.util.LinkedHashMap cannot be cast to xxx
java·spring boot
陈皮波比茶25 分钟前
计算机二级MySQL笔记
java·数据库
木井巳29 分钟前
【BFS/DFS 解决 FloodFill 算法】衣橱整理
java·算法·leetcode·深度优先·广度优先·宽度优先