c++中二维数组用int arr3定义,编译期确定尺寸、内存连续、访问快;std::vector则支持运行时动态尺寸但非连续内存、访问稍慢且需确保索引有效。

用 int arr[3][4] 定义固定大小二维数组最直接
这是 C++ 原生语法,编译期确定尺寸,内存连续,访问快。适合大小已知、不常变动的场景,比如棋盘、像素缓冲区。
注意:第一维是“行数”,第二维是“列数”,arr[2][3] 表示第 3 行第 4 列(下标从 0 开始)。
- 必须在定义时指定所有维度大小(除第一维可省略用于函数参数传参)
- 不能用变量初始化尺寸,
int n = 5; int arr[n][5];是非法的(C++ 标准不支持 VLAs) - 数组名
arr本身是首元素地址,类型为int (*)[4],不是int**
用 std::vector<:vector>></:vector> 动态创建更灵活
当行数、列数运行时才确定,或需要增删行/列时,必须用嵌套 vector。它本质是“一维 vector,每个元素是另一个 vector”,不是真正二维连续内存。
初始化常见写法:std::vector<:vector>> mat(3, std::vector<int>(4, 0));</int></:vector> —— 创建 3 行 × 4 列、初值为 0 的矩阵。
- 每行长度可以不同(即“锯齿数组”),
mat[0].resize(5)不影响其他行 - 访问仍用
mat[i][j],但底层两次指针跳转,比原生数组稍慢 - 别直接用
mat[i][j] = x访问未分配的索引,会触发未定义行为;先确保i 且 <code>j
arr[i][j] 访问时下标越界不会自动报错
C++ 原生数组和 vector 的 operator[] 都不做边界检查。越界读可能拿到垃圾值,越界写会破坏相邻内存,引发崩溃或逻辑错误,且调试困难。
- 开发阶段可用
vector::at()替代[]:如mat.at(i).at(j),越界抛std::out_of_range异常 - Clang/GCC 编译时加
-fsanitize=address可捕获多数越界访问(仅限调试) - 不要依赖
sizeof(arr)/sizeof(arr[0])算行数——对函数参数里的数组无效,因为退化为指针
传二维数组给函数时维度声明不能省略
函数形参若接收原生二维数组,第二维大小必须写死,例如:void func(int arr[][4], int rows) 或 void func(int (*arr)[4], int rows)。
- 第一维可省略(
[][4]),但第二维[4]必须显式写出,否则编译失败 - 不能写成
void func(int** arr, int rows, int cols)并直接传arr—— 类型不匹配,原生数组名不是int** - 用
std::vector就没这问题:void func(const std::vector<:vector>>& mat)</:vector>,干净通用
原生二维数组的“连续内存”特性常被误认为等价于指针数组,实际二者布局和语义完全不同;而 vector 的灵活性是以额外指针间接和内存碎片为代价的——选哪种,得看你到底要速度、安全,还是动态性。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











