最常用且安全的初始化方式是用构造函数一次性分配外层和内层容量,如vector mat(3, vector(4)); 行列顺序不可颠倒,否则逻辑错误。

vector> 声明时直接指定行列尺寸
最常用也最安全的初始化方式是用构造函数一次性分配好外层和内层容量。比如要建一个 3 行 4 列的 int 二维数组:
vector> mat(3, vector (4));
这里 vector 构造出一个含 4 个 0 的一维 vector,再被复制 3 次作为每行。注意:第二个参数是“拷贝构造子对象”,不是类型或大小数字。
- 如果想初始化为非零值(如 -1),写成
vector> mat(3, vector (4, -1)) - 不能写成
vector—— 编译失败,因为第二参数类型不匹配>(3, 4) - 这种写法在栈上只做一次内存分配(外层 vector),但每行仍各自在堆上分配,整体仍是动态的
逐行 push_back 或 resize 动态扩展
当行数或列数在运行时才确定,或需要按逻辑逐步填充时,先声明空容器,再用 push_back 或 resize 扩容:
vector> mat; mat.resize(3); // 外层预留 3 行(每行仍是空 vector) for (int i = 0; i < 3; ++i) { mat[i].resize(4, 7); // 每行设为 4 个元素,初值为 7 }
或者更常见的逐行构造:
立即学习“C++免费学习笔记(深入)”;
vector> mat; for (int i = 0; i < 3; ++i) { mat.push_back({1, 2, 3, 4}); // 直接推入 initializer_list }
-
push_back({1,2,3})要求编译器支持 C++11 及以上,且括号内必须是字面量或可隐式转换的列表 - 避免在循环里反复调用
push_back单个元素(如mat[i].push_back(x))—— 效率低,可能多次 realloc - 如果已知总大小,优先用第一种构造方式,减少内存碎片
用 vector 初始化 vector:避免浅拷贝陷阱
嵌套 vector 是值语义,赋值或传参时默认深拷贝。但要注意别误用指针或引用导致意外共享:
vectorrow = {1, 2, 3}; vector > mat(2, row); // OK:两行都是 {1,2,3} 的独立副本 row[0] = 99; // mat 不受影响
反例(常见错误):
vector> mat; vector * p = new vector ({1,2,3}); mat.push_back(*p); // 看似 OK,但若 p 后续被 delete,mat 里那行仍安全(已拷贝) // 真正危险的是:mat.push_back(*p); 再 later delete p; —— 没问题;但若写成 mat.push_back(*p), then p->clear(); —— 也不影响 mat
- 真正容易出错的是把
vector当参数传进函数后,在函数里修改了某一行的引用,结果影响到原始数据 —— 这不是 vector 本身的问题,而是你用了引用/指针却忘了语义>* - 除非明确需要共享数据,否则永远假设 vector 赋值 = 深拷贝;不要试图用
vector来“节省拷贝”然后乱改内容>&
性能与类型混用:int 和 double 别混在一个 vector> 里
vector 是强类型容器,vector 和 vector 完全不同,不能互相赋值或 push_back:
vector> int_mat = {{1,2},{3,4}}; vector > dbl_mat = {{1.0,2.0},{3.0,4.0}}; // int_mat = dbl_mat; // 编译错误 // int_mat.push_back(dbl_mat[0]); // 编译错误
- 如果需要混合数值类型,要么统一转成
double,要么用variant(C++17),但会显著增加复杂度, vector > - 读文件或解析输入时,务必提前确认数值精度需求;临时用
stoi/stod转换比让 vector 自动推导更可控 - 二维 vector 没有内置的“矩阵运算”能力,做乘法、转置等需手写循环或引入 Eigen/Boost
实际写的时候,最容易被忽略的是:构造时行列顺序不能颠倒 —— vector 是 rows 行、cols 列;反过来写就变成“每行只有 1 个元素,共 rows*cols 行”,调试时很难一眼发现。









