std::merge merging two std::vector coredump

std::merge merging two std::vector coredump

本文关键字:std coredump vector merging merge two      更新时间:2023-10-16

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

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 中使用任何其他合并功能吗?

谢谢!

问题是你的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));
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到底层容器中。

有关背面插入迭代器的信息,请参见此处。 back_inserter只是一个方便的函数,因此您不会编写大量模板参数。

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

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

大,无法容纳合并。 尝试:

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