std::merge 是最直接安全的有序序列合并方法,要求输入已排序、输出容器需预分配空间或使用插入迭代器,时间复杂度 O(m+n),稳定且无额外分配;手写双指针需正确处理边界,如一端遍历完后补全另一端剩余元素。

用 std::merge 是最直接安全的做法
标准库已经提供了专为有序序列合并设计的算法,std::merge 要求两个输入区间已排序,输出到目标容器(需预留足够空间或使用插入迭代器)。它时间复杂度 O(m+n),稳定且无额外分配开销。
常见错误是直接传入空 vector 并期望自动扩容——std::merge 不会自动 push_back,必须提前分配空间或配合 std::back_inserter:
std::vector<int> a = {1, 3, 5};
std::vector<int> b = {2, 4, 6, 7};
std::vector<int> result;
result.reserve(a.size() + b.size()); // 推荐:避免多次 realloc
std::merge(a.begin(), a.end(), b.begin(), b.end(), std::back_inserter(result));
注意:std::back_inserter 会让每次写入调用 push_back,虽方便但可能触发多次内存重分配;reserve + 普通迭代器更高效:
std::vector<int> result(a.size() + b.size()); std::merge(a.begin(), a.end(), b.begin(), b.end(), result.begin());
手写双指针合并时别忽略边界处理
手动实现能更好控制细节(比如去重、自定义比较),但容易在边界上出错:当一个 vector 遍历完,另一个剩余元素必须全部拷贝过去。
立即学习“C++免费学习笔记(深入)”;
典型漏掉的 case:
- 其中一个 vector 为空 → 循环不执行,结果为空
- 两个 vector 长度差异大 → 剩余部分没复制
正确写法要点:
- 用两个索引
i、j分别遍历a和b - 循环条件是
i - 循环结束后,分别用
while (i 和 <code>while (j 补全
示例片段:
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
std::vector<int> result;
result.reserve(a.size() + b.size());
size_t i = 0, j = 0;
while (i < a.size() && j < b.size()) {
if (a[i] <= b[j]) result.push_back(a[i++]);
else result.push_back(b[j++]);
}
while (i < a.size()) result.push_back(a[i++]);
while (j < b.size()) result.push_back(b[j++]);
合并后是否需要 std::inplace_merge?不需要
std::inplace_merge 适用于「单个 vector 中两段已排序子区间」的原地归并,比如 v = {1,3,5,2,4,6},前半和后半各自有序。它不适用于两个独立 vector 的合并。
误用场景:
- 把两个 vector 拼接后调用
inplace_merge→ 效率低(先insert或resize再合并,产生冗余拷贝) - 忘记指定中间迭代器位置 → 行为未定义
除非你明确在操作同一个容器内的分段数据,否则绕过这个函数,直接用 std::merge 或双指针。
性能与移动语义:注意 vector 元素类型影响
如果 vector 存的是大对象(如 std::string、自定义类),合并过程中的拷贝开销明显。C++11 后可利用移动语义优化:
-
std::merge本身不主动移动,但若源容器允许(比如你 move 出来临时 vector),目标容器接收时会触发移动构造 - 手写双指针时,可用
std::move显式转移(仅当确定源数据后续不再使用)
例如:
result.push_back(std::move(a[i++])); // 仅当 a 不再需要该元素时才安全
但多数情况下,对 int、double 等 trivial 类型,移动和拷贝无区别;对非 trivial 类型,优先保证逻辑正确,再考虑是否 move。
真正容易被忽略的是:合并后的 vector 如果后续只读,可以考虑用 std::span 或引用传递避免二次拷贝;如果只是临时拼接,甚至可以考虑不合并,改用多段视图联合迭代。

















