c – 如果我使用vector :: begin()而不是std :: back_inserter(vector)输出set_intersection会发生什么?

前端之家收集整理的这篇文章主要介绍了c – 如果我使用vector :: begin()而不是std :: back_inserter(vector)输出set_intersection会发生什么?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我一直在使用高度简洁直观的C语法来查找两个排序向量的交集,并将结果放在第三个向量中:
vector<bar> a,b,c;
//...
std::set_intersection(a.begin(),a.end(),b.begin(),b.end(),std::back_inserter(c));

这应该将c设置为交点(a,b),假设a和b被排序.

但是如果我只是使用c.begin()(我以为我在这里看到一个例子,那就是为什么我这样做)

std::set_intersection(a.begin(),c.begin());

set_intersection需要该参数的OutputIterator.我认为标准只需要c.begin()返回一个前向迭代器,我认为这可能是或不是一个OutputIterator.

无论如何,代码用c.begin()编译在clang下.

什么保证在标准下发生?如果这个编译,可能会发生什么 – 也就是说,当c.begin()返回的迭代器最终会超过向量的结尾时,并尝试访问指向的元素,那么/可能会发生什么?在这种情况下,一个符合一致的实现会静止地扩展向量,所以begin()实际上是一个像back_inserter这样的附加的OutputIterator呢?

我主要是要了解标准如何与迭代器一起工作:真正发生了什么,所以我可以超越使用STL的复制和粘贴.

解决方法

输出迭代器的重要要求是对输出范围[输出,输出大小]有效且可写.

传递c.begin()将导致覆盖的值只有在容器c拥有足够的元素才能覆盖的情况下才起作用.想象一下,c.begin()返回一个指向大小为0的数组的指针 – 那么你在写* out = 7时会看到这个问题.

back_inserter将每个分配的值添加到向量(通过push_back),并提供使STL算法扩展范围的简明方法 – 它重载用于迭代器的运算符.

从而

std::set_intersection(a.begin(),c.begin());

一旦set_intersection向其输出迭代器写入一些东西,也就是当a和b的设置交集不为空时,将调用未定义的行为.

Can a conforming implementation silently extend the vector in this case,so that begin() is in fact an appending OutputIterator like back_inserter is?

当然.这是未定义的行为. (这是一个幽默的方式,告诉你,你甚至不应该考虑使用这个,无论对任何实现的影响.)

猜你在找的C&C++相关文章