C++中二维数组标准访问为arrayi,i行j列从0开始;声明需指定列数,动态分配常用int**;vector虽支持i但内存不连续;函数传参必须明确列数或扁平化处理。

用方括号语法直接访问 array[i][j]
二维数组在 C++ 中本质是“数组的数组”,所以标准访问方式就是连续两个方括号:array[i][j]。其中 i 是行索引,j 是列索引,都从 0 开始。
注意:编译器不会检查越界,array[5][0] 访问一个只有 3 行的数组会导致未定义行为——可能读到垃圾值、崩溃,或看似正常但埋下隐患。
- 声明时必须指定列数(第二维大小),例如
int grid[4][5];合法,int grid[][5];在函数参数中也合法,但int grid[][];直接报错 - 如果用
new动态分配,常见写法是int** mat = new int*[rows]; for(...) mat[i] = new int[cols];,此时mat[i][j]仍可用,但底层不是连续内存 - 访问速度最快,因为是直接地址计算:
&array[0][0] + i * cols + j
用指针算术访问 *(array[i] + j) 或 *(*array + i * cols + j)
既然二维数组名退化为指向首行的指针(类型如 int (*)[5]),那它支持指针运算。两种常用展开方式:
-
*(array[i] + j):先取第i行(array[i]是int[5],自动转为int*),再偏移j个元素 -
*(*array + i * cols + j):把整个二维数组看作一维,*array等价于&array[0][0],然后按行优先算总偏移 - 第二种写法要求你显式知道列数
cols;第一种更接近直觉,但别误写成*(array + i)[j]—— 这会先对array做指针加法(步长是整行大小),再取[j],结果一样但可读性差
用 std::vector<:vector>></:vector> 时避免常见陷阱
很多人改用 vector 是为了动态尺寸和边界检查,但要注意它和原生数组行为不等价:
立即学习“C++免费学习笔记(深入)”;
-
vec[i][j]语法可用,但vec[i]返回的是std::vector<int>&</int>,每次调用operator[]都有函数调用开销(虽然通常被内联) -
vec.at(i).at(j)会抛出std::out_of_range异常,适合调试阶段,但别在热循环里用 - 真正坑的是内存布局:每个
vector单独分配,vec[0]和vec[1]的数据不一定相邻——想用一维方式遍历?不行。想传给只接受int*的 C 函数?得单独拷贝或改用std::vector<int></int>扁平存储
传参时怎么让函数接收二维数组
函数参数不能只写 int arr[][],编译器需要知道列数才能算地址。正确写法有三种:
- 指定第二维:
void func(int arr[][5], int rows)—— 最常见,arr类型是int (*)[5] - 用指针加列数:
void func(int (*arr)[5], int rows)—— 和上一条等价,更体现类型本质 - 扁平化传一维指针:
void func(int* arr, int rows, int cols),调用时传&grid[0][0],访问用arr[i * cols + j]—— 灵活且内存连续,C 风格库常用 - 别写
void func(int arr[3][5]):数组长度在参数里只是摆设,会被忽略
最易被忽略的一点:如果你用 constexpr 尺寸的数组(比如 int a[2][3]),而函数期待 int[][4],类型就不匹配——C++ 不做隐式尺寸转换,哪怕逻辑上能兼容。这时候要么改声明,要么用模板推导尺寸。


















