std :: merge合并两个std :: vector coredump

时间:2012-02-02 15:57:33

标签: c++ stl merge

以下代码以核心转储结束。 我做错了什么?

std::vector<int> a;
a.push_back(1);
a.push_back(4);
a.push_back(7);
std::vector<int> b;
b.push_back(2);
b.push_back(5);
b.push_back(8);
std::vector<int> c;
c.clear();


std::merge(a.begin(), a.end(), b.begin(), b.end(), c.begin());
for (it=c.begin(); it!=c.end(); ++it)
    std::cout << *it << endl;

我可以使用stl或boost中的其他合并函数吗?

谢谢!

4 个答案:

答案 0 :(得分:9)

问题是你的c是空的,因为它是在没有元素的情况下初始化的,更不用说对clear()的不必要的调用了。 std::merge()输出迭代器作为其最后一个参数。如果c.begin()指的是已经包含足够元素的std::vector的开头,那么这不是问题 - 这些元素只会被覆盖。实际上,您通过将值写入内存过去向量的末尾来调用未定义的行为。

为确保c有足够的空间容纳元素,您可以这样做:

c.resize(a.size() + b.size());
std::merge(a.begin(), a.end(), b.begin(), b.end(), c.begin());

但是,使用调用std::back_insert_iterator的输出迭代器push_back()更为惯用。为了提高效率,您可以事先在向量上调用reserve()。这确保c只需要分配一次内存,而不是在调用std::merge()期间增长。最终解决方案如下所示:

#include <iterator>

// ...

c.reserve(a.size() + b.size());
std::merge(a.begin(), a.end(), b.begin(), b.end(), std::back_inserter(c));

答案 1 :(得分:2)

std::merge(a.begin(), a.end(), b.begin(), b.end(), std::back_inserter(c));
                                                   ^^^^^^^^^^^^^^^^^^^^^^^

问题是如果你传递c.begin(),合并函数将开始将值写入*c.begin()*(c.begin() + 1)等,这会导致未定义的行为,包括核心转储。你有两个选择。

  • 确保c足够大,以容纳合并将要写入的所有值。例如,您可以在致电c.resize(a.size()+b.size());
  • 之前致电merge
  • 通过std::back_insert_iterator。它的例子在我的答案的开头给出。每次*it = x itback_insert_iterator时,它都会push_back x进入基础容器。

可以找到有关后插入迭代器的信息hereback_inserter只是一个便利功能,因此您不会编写很多模板参数。

答案 2 :(得分:2)

您试图将结果存储在c中,这是空的,因此,它没有足够的空间来存储它们(实际上,它没有足够的空间来存储任何)。尝试使用back_insert_iterator代替push_back元素:

std::merge(a.begin(), a.end(), b.begin(), b.end(), std::back_inserter(c));

答案 3 :(得分:1)

c不足以保持合并。尝试:

#include <iterator>
...
std::merge(a.begin(), a.end(),
           b.begin(), b.end(),
           std::back_inserter(c));