应使用单次分配的连续一维数组模拟二维访问,即int data = new int[rows cols]{},通过data[i cols + j]访问元素,释放时仅需delete[] data;new int[rows]和vector均导致内存不连续、缓存不友好。

new int*[rows] 分配的是指针数组,不是连续二维数组
很多人以为 new int*[rows] 就能拿到一块连续内存的二维数组,其实它只分配了 rows 个 int* 指针的空间,每个指针再单独 new int[cols],最终是 rows + 1 次堆分配,内存不连续,缓存不友好,释放还容易漏。
- 真实布局:指针数组(首地址)→ 指向
rows个分散的int[cols]块 - 后果:CPU 预取失效、TLB 命中率低、
delete[]必须逐行调用,漏一次就泄漏 - 正确目标:单次
new int[rows * cols],然后手动算下标
用 int* + 行列计算模拟二维访问,最简且连续
只要保证底层是一整块 int[rows * cols],就能用 ptr[i * cols + j] 安全替代 arr[i][j]。这是 C++ 里最轻量、最可控的连续二维布局方案。
- 分配:
int* data = new int[rows * cols]{}(花括号初始化为 0) - 访问:
data[i * cols + j],注意别越界——i范围[0, rows),j范围[0, cols) - 释放:
delete[] data,仅一次,无遗漏风险 - 兼容性:所有标准 C++ 编译器都支持,无 ABI 或对齐隐患
vector> 看似方便,但默认不连续
vector<vector>></vector> 是常见误选:它确实语法上像二维数组,但每个内层 vector 单独堆分配,和 new int*[rows] 本质一样,只是多了 vector 的管理开销。
- 错误现象:
&v[0][0]和&v[1][0]地址差远不止cols * sizeof(int) - 想连续?只能用
vector<int></int>扁平化存储,自己封装at(i, j)方法 - 性能影响:随机访问时 cache line 利用率比连续布局低 3–5 倍(实测常见于图像处理循环)
new int[rows][cols] 编译不过,因为维度必须是常量
你写 int (*arr)[cols] = new int[rows][cols] 会报错——cols 不是编译期常量,C++ 不允许运行时决定的内置数组维度。
立即学习“C++免费学习笔记(深入)”;
- 错误信息:
error: variable length array declaration not allowed at file scope(或类似) - 即使
cols是const int,若未在编译期确定(比如来自函数参数),依然不合法 - 替代方案只有两种:扁平
int*+ 手动索引,或用std::unique_ptr<int></int>包装(C++14 起支持运行时长度)
真正要“连续”,就得放弃语法糖;data[i * cols + j] 看着土,但它是唯一不绕弯、不隐式分配、不依赖编译器扩展的解法。越想省事用 [][],越容易掉进内存碎片和缓存失效的坑里。









