




推荐用new分配连续内存的二维数组:先new int[rowscols]获数据区,再new int[rows]建行指针,循环设arr[i]=data+i*cols;释放时先delete[] data后delete[] arr;非连续方式需逐行new并遍历delete[],易泄漏。
这种写法本质是申请一块连续内存,再用指针偏移模拟二维访问,内存局部性好、释放只需一次 delete[],适合行数列数在运行时确定但固定不变的场景。
常见错误是把 int** arr 和连续内存混用,导致越界或释放崩溃。
int* data = new int[rows * cols];
int** arr = new int*[rows];,然后循环赋值 arr[i] = data + i * cols;
arr[i][j],但底层是线性地址 data[i * cols + j]
delete[] data;,再 delete[] arr;(不能反过来,也不能只删一个)逐行 new int[cols],每行内存可能分散在堆不同位置。容易写出,但缓存不友好、释放麻烦、易漏删某一行。
典型错误是只调用 delete[] arr; 而忘记遍历删除每行,造成严重内存泄漏。
int** arr = new int*[rows];
for (int i = 0; i
for (int i = 0; i ,然后 delete[] arr;
new int[cols] 抛异常,已有行需手动回滚释放,否则泄漏它确实是更安全的选择,但行为上不是二维数组——vector 的每行是独立分配的,内存不连续,且 resize() 可能触发整行拷贝;而 C 风格二维数组强调的是“一块内存+双重下标访问”语义。
如果你需要传递给 C 接口(如 OpenGL、FFmpeg),或做高性能数值计算(如矩阵乘法),vector 无法直接传 int** 或 int*,必须额外拷贝或重构。
vector> 的 &v[0][0] 仅在首行非空时有效,且仅保证该行连续vector + 手动索引:v[i * cols + j]
int** 等价物,无法满足要求二级指针的旧 APIC++11 起默认 new 抛 std::bad_alloc,不会返回 nullptr。想用 nullptr 检查,得显式加 std::nothrow。
连续内存分配失败风险更高(大块内存难找),非连续方式可能某一行失败而前面已成功,状态不一致。
int* data = new (std::nothrow) int[rows * cols];,检查 if (!data) { /* 处理 */ }
k 行 new
int[cols] 失败,前 k 行需立即释放,否则泄漏std::unique_ptr 管理(如 std::unique_ptr data + std::unique_ptr arr )实际项目里,除非对接 C 接口或有极致性能要求,否则优先用 std::vector<:vector>> 或单维 std::vector 加索引计算;真要用 new,第一种连续内存写法更可控,但所有手动内存管理都绕不开“分配-使用-释放”三步的精确匹配。