二维数组名不是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 <h3>用<code>int(*)[N]</code>才是访问栈上二维数组的正解</h3><p>对于 <code>int arr[3][4]</code> 这类栈分配的二维数组,应使用指向数组的指针,例如:</p><div class="aritcle_card flexRow artxards"> <div class="artcardd flexRow"> <a class="aritcle_card_img" rel="nofollow" href="/xiazai/skill2659" title="C++"><img src="https://img.php.cn/upload/skill/000/000/081/178927213426672.jpg" alt="C++" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a> <div class="aritcle_card_info flexColumn"> <a rel="nofollow" href="/xiazai/skill2659" title="C++" class="overflowclass">C++</a> <p class="overflowclass">"空空如也"</p> </div> <a rel="nofollow" href="/xiazai/skill2659" title="C++" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span> </a> </div> </div>
-
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,它能安全桥接各种布局。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










