如果我使用vector :: begin()而不是std :: back_inserter(vector)来输出set_intersection会发生什么? [英] What happens if I use vector::begin() instead of std::back_inserter(vector) for output of set_intersection?

查看:180
本文介绍了如果我使用vector :: begin()而不是std :: back_inserter(vector)来输出set_intersection会发生什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在使用高度简洁直观的C ++语法来查找两个已排序的向量的交集,并将结果放在第三个向量中

I have been using the highly concise and intuitive C++ syntax for finding the intersection of two sorted vectors and putting the result in a third vector:

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 已排序。

This should set c to intersection(a,b), assuming a and b are sorted.

但如果我只使用 c.begin()(我以为我在某个地方看到了一个例子,这就是我做的原因):

But what if I just use c.begin() (I thought I saw an example somewhere of this, which is why I did):

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

set_intersection 预计该参数的OutputIterator 。我认为标准只需要 c.begin()返回转发迭代器,我想这可能会也可能不会是 OutputIterator

set_intersection expects an OutputIterator at that parameter. The standard I believe requires only that c.begin() return a forward iterator, which I suppose might or might not be an OutputIterator.

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

Anyway, the code with c.begin() compiled under clang.

根据标准,保证会发生什么?如果这个编译,可能会发生什么 - 也就是说,当 c.begin()返回的迭代器最终增加超过向量的末尾时,并且尝试是是为了访问指向的元素,必须/可能发生什么?在这种情况下,符合标准的实现可以无提示地扩展向量,因此 begin()实际上是附加 OutputIterator 之类的 back_inserter 是吗?

What is guaranteed to happen under the standard? If this compiles, what is likely to happen - that is, when the iterator returned by c.begin() is eventually incremented past the end of the vector, and an attempt is made to access the element pointed to, what must/may happen? Can a conforming implementation silently extend the vector in this case, so that begin() is in fact an appending OutputIterator like back_inserter is?

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

I'm asking this mainly to understand how the standard works with iterators: what's really going on, so I can move beyond copy-and-paste in using the STL.

推荐答案

输出迭代器的重要要求是它是有效且可写的范围
[out,out + 输出大小

The important requirement for an output iterator is that it be valid and write-able for the range
[out, out+size of output).

传递 c.begin()将导致值覆盖,仅当容器 c 包含足够的要覆盖的元素时才有效。想象一下, c.begin()返回一个指向大小为0的数组的指针 - 然后在编写 * out ++ = 7时会看到问题。

Passing c.begin() will lead to the values being overwritten which only works if the container c holds enough elements to overwrite. Imagine that c.begin() returns a pointer to an array of size 0 - then you'll see the problem when writing *out++ = 7;.

back_inserter 将每个指定值添加到a vector (通过 push_back )并提供一种使STL算法扩展范围的简洁方法 - 它使运算符重载适当地用于迭代器。

back_inserter adds every assigned value to a vector (via push_back) and provides a concise way of making the STL-algorithms extend a range - it overloads the operators that are used for iterators appropriately.

因此

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

一旦 set_intersection 写入内容,就会调用未定义的行为它的输出迭代器,也就是说,当 a b 的集合交集不为空时。

invokes undefined behavior once set_intersection writes something to its output iterator, that is, when the set intersection of a and b isn't empty.


在这种情况下,符合标准的实现是否可以静默扩展向量,因此begin()实际上是附加的 OutputIterator 喜欢 back_inserter 是吗?

当然。这是未定义的行为。 (这是一种幽默的方式告诉你,你不应该考虑使用它,不管对任何实现的影响。)

Of course. It's undefined behavior. (This is a humorous approach of telling you that you shouldn't even consider using this, no matter the effects on any implementation.)

这篇关于如果我使用vector :: begin()而不是std :: back_inserter(vector)来输出set_intersection会发生什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆