vector是最常用且安全的二维动态数组写法,支持动态增行增列和自动内存管理;常见错误包括非法声明vector或手动new导致泄漏;初始化、追加和访问方式均有明确规范。

vector> 是最常用且安全的二维动态数组写法
直接用 vector<vector>></vector> 声明,就能得到行为接近二维数组的结构,支持动态增行、增列,内存自动管理。它不是“真”的连续二维内存(即不是单块 int*),但对绝大多数业务场景足够高效且不易出错。
常见错误是试图用 vector<int></int> 或 vector<int></int> —— 这在 C++ 中非法,因为数组类型不可拷贝、不可默认构造;也有人误用 vector<int>*</int> 手动 new 二维,结果忘了 delete 或导致内存泄漏。
- 初始化空二维容器:
vector<vector>> mat;</vector> - 初始化 3 行、每行 4 个 0:
vector<vector>> mat(3, vector<int>(4, 0));</int></vector> - 追加一行:
mat.push_back({1, 2, 3});或mat.emplace_back(3, 5);(建 3 个值为 5 的元素) - 访问元素:和普通二维数组一样,
mat[i][j],但需确保i 且 <code>j
需要连续内存时,用一维 vector 模拟二维索引
如果算法对缓存友好性敏感(比如图像处理、矩阵乘),或者要传给要求 int* 的 C 接口,就不能用嵌套 vector。此时应只用一个 vector<int></int> 存所有数据,自己算下标。
例如 m 行 n 列矩阵中,第 i 行第 j 列对应一维索引 i * n + j。注意:这要求每行长度固定,且必须提前知道列数 n。
- 分配:
vector<int> data(m * n, 0);</int> - 写入第 i 行第 j 列:
data[i * n + j] = val; - 读取:
int x = data[i * n + j]; - 传给 C 函数:
some_c_func(data.data(), m, n);(data.data()返回int*)
resize() 和 reserve() 的区别直接影响性能
对 vector<vector>></vector> 调用 resize() 会构造/析构子 vector;而 reserve() 只预分配外层数组容量,不碰内层。频繁 push 行但每行大小不定时,建议先 mat.reserve(expected_row_count) 避免外层 vector 重分配。
- 错误用法:
mat.reserve(100); mat[5].push_back(1);→mat[5]越界,reserve()不改变size() - 正确扩容行:
mat.resize(10);后mat[0]到mat[9]都是合法的空vector<int></int> - 高效添加多列:对某一行调用
mat[i].reserve(col_count),避免该行内部反复 realloc
别用 vector 当二维布尔矩阵
vector<bool></bool> 是特化模板,内部按位存储,operator[] 返回的是代理对象而非 bool&,导致 vector<vector>></vector> 的 mat[i][j] = true 可能不工作或行为异常(尤其在取地址、绑定引用时)。
- 替代方案:用
vector<vector>></vector>(每个char占 1 字节,可寻址)、vector<bitset>></bitset>(列数固定时)、或直接vector<bool></bool>+ 一维模拟二维 - 验证方式:写
auto& ref = mat[i][j];,若编译失败,基本就是掉进vector<bool></bool>陷阱了
实际项目里,90% 的二维动态需求用 vector<vector>></vector> 就够了。真正卡性能或对接 C 接口时,才值得切到一维模拟——但得自己管好行列逻辑,漏掉边界检查或算错索引,比嵌套 vector 更难 debug。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











