C++中merge合并已排序vector出现段错误的原因及解决
原代码触发段错误的核心原因
这是std::merge使用中非常常见的误区——你忽略了目标容器v3的空间准备!
std::merge的设计逻辑是不会自动为目标容器分配内存的,它只会将合并后的元素依次写入你提供的目标迭代器(也就是你代码里的v3.begin())指向的位置。如果v3的当前大小/容量小于v1.size() + v2.size(),当merge尝试写入超出v3合法内存范围的区域时,就会触发内存越界访问,直接导致段错误。
举个典型的错误场景:如果你的v3是默认初始化的空vector,v3.begin()指向的是一个空的内存位置,后续写入操作完全是在非法内存区域进行,必然崩溃。
两种可行的解决方案
方案1:提前为v3分配足够的空间
在调用merge之前,先通过resize为v3预留刚好能容纳合并后所有元素的空间:
#include <algorithm> #include <vector> int main() { std::vector<int> v1 = {3,1,4}; std::vector<int> v2 = {2,5,0}; std::vector<int> v3; std::sort(v1.begin(), v1.end()); std::sort(v2.begin(), v2.end()); // 关键:提前分配足够空间 v3.resize(v1.size() + v2.size()); std::merge(v1.begin(), v1.end(), v2.begin(), v2.end(), v3.begin()); // 此时v3就是合并后的有序数组 return 0; }
为什么有效?:resize会让v3的大小变为v1.size()+v2.size(),同时分配对应的内存空间,merge写入时所有操作都在v3合法的内存范围内,不会出现越界问题。
方案2:使用std::back_inserter动态添加元素
如果你不想手动计算和分配空间,可以用std::back_inserter作为目标迭代器,它会自动调用v3.push_back()来添加元素,无需提前准备空间:
#include <algorithm> #include <vector> #include <iterator> // 必须包含这个头文件才能使用back_inserter int main() { std::vector<int> v1 = {3,1,4}; std::vector<int> v2 = {2,5,0}; std::vector<int> v3; std::sort(v1.begin(), v1.end()); std::sort(v2.begin(), v2.end()); // 使用back_inserter,无需提前resize std::merge(v1.begin(), v1.end(), v2.begin(), v2.end(), std::back_inserter(v3)); return 0; }
为什么有效?:std::back_inserter返回的是一个插入迭代器,每次merge需要写入元素时,都会调用目标容器的push_back方法,动态扩展容器的内存,完全避免了手动管理空间的麻烦,也从根源上杜绝了越界问题。
额外注意点
你已经正确地对v1和v2做了排序,这一点完全符合std::merge的要求(它要求输入的两个范围必须是有序的,否则合并结果会无序),所以这部分没问题,核心问题就是目标容器的空间准备。
内容的提问来源于stack exchange,提问作者Neer Patel

