二维数组名不是int,直接赋值会出错;其类型为int()[4],与int内存布局和语义不同,强转后解引用易越界;需手动构造指针数组:先分配连续内存data,再分配指针数组pp,使pp[i]指向data[icols]。

二维数组名不是int**,直接赋值会出错
很多人写 int arr[3][4]; int** p = arr; 编译就报错,比如 cannot convert 'int (*)[4]' to 'int**'。这是因为 arr 的类型是 int (*)[4](指向含 4 个 int 的数组的指针),而 int** 是“指向 int* 的指针”,二者内存布局和语义完全不同。强行 reinterpret_cast 强转后解引用,大概率访问越界或读到垃圾值。
想用int**访问二维数组,必须手动构造指针数组
只有当二维数据以“指针数组 + 独立内存块”方式组织时,int** 才能安全使用。典型做法:
- 先用
new int[rows * cols]分配一块连续内存 - 再用
new int*[rows]分配指针数组 - 把每行首地址填进指针数组:
pp[i] = &data[i * cols]
示例:
int rows = 3, cols = 4;
int* data = new int[rows * cols];
int** pp = new int*[rows];
for (int i = 0; i < rows; ++i) {
pp[i] = &data[i * cols];
}
// 使用:pp[i][j] 等价于 data[i * cols + j]
pp[1][2] = 42;用int(*)[N]才是访问栈上二维数组的正解
对于 int arr[3][4] 这类栈分配的二维数组,应使用指向数组的指针,例如:
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
立即学习“C++免费学习笔记(深入)”;
-
int (*p)[4] = arr;→ 类型匹配,p[1][2]正确访问第 1 行第 2 列 - 函数传参时也必须带列数:
void f(int (*a)[4], int rows) - 不能省略
[4],否则编译器无法计算行偏移
如果列数不固定,就得改用一维数组加手动索引:arr[i * cols + j],或者用 std::vector<:vector>></:vector>。
性能与可维护性提醒
int** 方式虽然支持不规则行长度,但有明显代价:
- 内存不连续 → 缓存不友好,访问速度慢
- 需手动管理两层内存(
delete[] pp和delete[] data),容易漏删或错删 - 无法用
sizeof得到总大小,也不能靠数组名推导维度
除非真需要每行动态长度,否则优先用 int (*)[N] 或 std::vector<:array n>></:array>。C++20 还可考虑 std::mdspan,它能安全桥接各种布局。

















