以下代码最终以核心转储结束.我做错了什么?
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;
Run Code Online (Sandbox Code Playgroud)
在我可以使用的stl或boost中是否还有其他合并功能?
谢谢!
Jon*_*rdy 10
问题是你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());
Run Code Online (Sandbox Code Playgroud)
但是,使用一个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));
Run Code Online (Sandbox Code Playgroud)
std::merge(a.begin(), a.end(), b.begin(), b.end(), std::back_inserter(c));
^^^^^^^^^^^^^^^^^^^^^^^
Run Code Online (Sandbox Code Playgroud)
问题是,如果您传递c.begin(),合并函数将开始将值写入*c.begin()等*(c.begin() + 1),这会导致未定义的行为,包括核心转储。这里你有两个选择。
c足够大以容纳合并要写入其中的所有值。例如,您可以c.resize(a.size()+b.size());在调用之前调用mergestd::back_insert_iterator. 我的答案一开始就给出了它的例子。每次执行*it = xwhere itis a时back_insert_iterator,它都会 push_backx 到底层容器中。有关后插入迭代器的信息可以在此处找到。back_inserter只是一个方便的函数,这样您就不必编写大量模板参数。
| 归档时间: |
|
| 查看次数: |
2915 次 |
| 最近记录: |