int**分配二维数组必须两层释放,因外层只分配行指针数组,内层每行数据是独立堆块;单次delete[] arr会导致内存泄漏或未定义行为。

直接用 int** 手动分配二维数组,却只调用一次 delete[] arr,是内存泄漏的高发场景——90% 以上的相关泄漏都源于此。
为什么 int** 分配必须两层释放?
因为 int** arr = new int*[rows] 只分配了“行指针数组”,每行实际数据(new int[cols])是独立堆块,地址不连续。操作系统把它们当 1 + rows 个独立内存块管理,只删外层数组根本不管内层。
- 漏掉某次
delete[] arr[i]→ 对应那行内存永久丢失 - 先
delete[] arr再删各行 →arr[i]变成悬挂指针,delete[]行为未定义(可能崩溃) - 某次
new int[cols]抛异常 → 前面已成功分配的几行必须立即手动清理,否则泄漏
new int[rows * cols] 单次分配更安全
用一维连续内存模拟二维,避免多级指针管理。关键不是“省事”,而是把释放责任压缩到一次 delete[]。
- 分配:
int* data = new int[rows * cols]; int** arr = new int*[rows];,再循环arr[i] = data + i * cols; - 释放顺序严格:先
delete[] data;,再delete[] arr;(反序会崩) - 若只需遍历或固定索引,直接用
data[i * cols + j],跳过arr[i][j]的两次指针解引用,性能更好
智能指针能自动管 int** 吗?
不能。std::unique_ptr<int></int> 只支持一维连续内存,它不知道你建的 int** 中间指针数组的存在,也不会帮你调用 delete[] 每行。
立即学习“C++免费学习笔记(深入)”;
- 想用 RAII,得自己封装:例如用
std::unique_ptr<int></int>管理data,再用std::vector<:unique_ptr>></:unique_ptr>管各行(但失去arr[i][j]语法) - 最简方案:改用
std::vector<:vector>></:vector>—— 它自动析构每行,且支持vec[i][j],除非要对接 C 接口或极端性能敏感 - 若必须裸指针,至少把分配/释放逻辑封进类,构造函数分配、析构函数确保双层
delete[]
真正容易被忽略的是异常路径:哪怕只有一行 new int[cols] 失败,前面成功的所有行都得在 catch 块里逐个 delete[],否则就是隐性泄漏——这种分支往往测试覆盖不到。


















