“数组的数组”指每个子数组独立分配、长度可变的嵌套结构,而非内存连续的二维数组;c++中应使用std::vector实现,避免t**手动管理或intn固定尺寸陷阱。

什么是“数组的数组”?先说清楚它不是什么
很多人看到“数组的数组”,第一反应是 int arr[3][4] 这种二维数组——但它在内存里是连续的一块,本质是“一维数组的别名”,不是真正意义上的“数组套数组”。C++ 里真想让每个子数组独立分配、长度不一、甚至后期重分配,就得用 std::vector<:vector>></:vector> 或者手动管理 T**。前者安全常用,后者灵活但危险。
用 vector> 实现可变长度的数组嵌套
这是最推荐的方式,尤其当你需要每行长度不同(比如稀疏矩阵、三角形结构)或运行时才知道尺寸时:
-
std::vector<:vector>> grid;</:vector>声明空容器,后续用push_back添加行 -
grid.resize(5);预分配 5 行,但每行仍是空的;要填内容得再对每行调用resize或assign -
grid[0].push_back(42);向第 0 行末尾加元素——注意:必须确保grid[0]已存在(比如先grid.resize(1)或grid.emplace_back()) - 别直接写
grid[0][0] = 1,除非你确认该位置已分配,否则触发未定义行为
用 T[N][M] 定义固定尺寸二维数组的陷阱
这种写法看似简单,但容易误判类型和传递规则:
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
-
int a[2][3];类型是int[2][3],不是int**,也不是int*;传参时必须写成void f(int arr[2][3])或更通用的void f(int (*arr)[3], int rows) - 不能用
auto x = a;直接推导出完整类型,会退化为指针;要用decltype(a)或using Arr2D = int[2][3]; - 初始化时
int b[2][3] = {{1,2},{3,4}};会补零,但{{1,2,3},{4}}是合法的——第二行只初始化前 1 个元素,其余为 0
手动管理 new T*[N] + new T[M] 的风险点
只有极少数场景(如对接 C 接口、极致性能控制)才考虑这个,但必须自己处理全部生命周期:
int** mat = new int*[rows]; for (int i = 0; i —— 忘记某层 <code>delete[]就内存泄漏- 不能用
delete mat,必须for (int i = 0; i - 异常安全差:中间某次
new失败,前面已分配的内存没地方自动释放 - 现代 C++ 基本不用它,
std::vector在绝大多数场景下性能足够,且不会漏掉析构
真正难的不是怎么写出来,而是判断该用哪一种——固定尺寸、编译期可知?选 T[N][M];需要动态增删、不规则形状?选 vector<vector>></vector>;非要裸指针?先问自己能不能用 unique_ptr 包一层。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










