正确写法是v1.insert(v1.end(), v2.begin(), v2.end());不可用v2整体传入,避免迭代器失效、类型不匹配及空容器data()解引用未定义等问题。

vector::insert 合并两个 vector 的正确写法
直接用 insert 合并两个 std::vector 是可行的,但必须注意插入位置和迭代器有效性。最常见错误是误用 end() 位置却传入错误范围,导致编译失败或越界。
假设你有两个 vector:v1 和 v2,想把 v2 全部追加到 v1 末尾:
v1.insert(v1.end(), v2.begin(), v2.end());
这是安全且高效的写法,底层会调用移动/拷贝构造,时间复杂度 O(n),空间上不额外分配(除非触发扩容)。
- 不能写成
v1.insert(v1.end(), v2)——insert没有接收整个 vector 的重载 - 若想插在开头:
v1.insert(v1.begin(), v2.begin(), v2.end()),但性能差(每插一个元素都可能搬移后续) - 若
v2是右值(如临时对象),可考虑用std::move_iterator避免深拷贝,但需确保v2后续不再使用
用 insert 合并时容易踩的坑
最典型的是迭代器失效和类型不匹配。比如:
立即学习“C++免费学习笔记(深入)”;
-
v2是vector,而v1是vector,v1.insert(..., v2.begin(), v2.end())编译失败 —— 类型不兼容,不会隐式转换 - 在循环中边遍历边用
insert修改同一容器,会导致迭代器失效,行为未定义 - 误把
v2.data()当作迭代器传入:例如v1.insert(v1.end(), v2.data(), v2.data() + v2.size())看似等价,但若v2为空,v2.data()可能为 nullptr,解引用未定义 - 用
push_back循环替代insert批量插入,效率低且可能多次 realloc
比 insert 更合适的合并方式:insert vs. splice vs. assign
对于 std::vector,insert 是通用选择,但要注意它不提供“窃取”语义。如果你用的是 std::list 或 std::deque,splice 才是零开销合并;而 vector 没有 splice。
- 如果目标是清空
v1再装入v2内容,直接v1 = std::move(v2)更高效(C++11 起支持移动赋值) - 如果只是追加且已知容量足够,
v1.reserve(v1.size() + v2.size())配合insert可避免中间扩容 - 不要用
assign替代insert:v1.assign(v2.begin(), v2.end())会丢弃v1原有内容,不是“合并”
insert 的参数类型和 const 正确性
insert 的区间重载签名是:iterator insert(const_iterator pos, InputIt first, InputIt last)。关键点在于:
-
pos必须属于当前 vector,且不能是v2的迭代器(哪怕类型相同也不行) -
first和last必须是合法输入迭代器,指向同一容器或支持解引用和自增的范围 - 若
v2是 const vector,v2.begin()返回const_iterator,仍可传给insert—— 输入迭代器不要求可写 - 不能传裸指针到非连续容器(如
std::list),但vector支持指针作为随机访问迭代器
真正容易被忽略的是:当 v1 和 v2 元素类型含非平凡移动构造函数时,insert 是否触发移动而非拷贝,取决于编译器优化和类型是否满足 is_nothrow_move_constructible —— 这会影响异常安全性,但日常使用通常无需干预。











