为什么std :: advance不返回生成的迭代器?

时间:2015-06-21 15:11:59

标签: c++ iterator c++-standard-library

目前,std::advance的设计如下:

template< class InputIt, class Distance >
void advance( InputIt& it, Distance n );

但是,我经常发现自己想要的东西:

template< class InputIt, class Distance >
InputIt advance( InputIt it, Distance n );

那么,当前设计的基本原理是什么?这是出于性能考虑吗?请注意,std::nextstd::prev会返回生成的迭代器。

2 个答案:

答案 0 :(得分:1)

没有技术原因阻止它将引用返回到输入值,并且任何合理的编译器应该能够在不使用的情况下优化返回值。所以如果他们愿意,他们可以这样做。

我认为从API设计的角度来看,他们的选择是有道理的 - std::prevstd::next采用迭代器并返回分别指向上一个或下一个元素的不同迭代器不修改输入

另一方面,

std::advance修改输入。如果它返回对输入迭代器的引用,则可能会混淆一个函数,该函数返回一个副本而不会就地修改输入。这可能是危险的。

请注意std::advanceInputIterator一起使用,其中包括迭代具有副作用的迭代器(诸如从流中读取的迭代器之类的东西),但是std::prevstd::next仅适用于ForwardIterator s,没有副作用。

因此,返回单独的(如std::prevstd::next)将是一个坏主意 - 您最终会在同一个流上返回两个迭代器,这可能会对彼此造成不利影响。

答案 1 :(得分:0)

正如评论部分所示,主要原因是InputIterator不能保证在递增迭代器之后,任何先前的迭代器仍然有效:

  

InputIterators仅保证单通道算法的有效性:一旦InputIterator i递增,其先前值的所有副本都可能无效。

因此,如果std::advance返回一个副本,则调用者可能最终得到两个迭代器,其中一个可能无效。带引用的接口表明这不是输入迭代器的使用方式。

另一方面,

std::prevstd::next采用BidirectionalIterator,其中包括满足ForwardIterator的要求:

  

与InputIterator和OutputIterator不同,它可用于多通道算法。

因此,您可以移动迭代器,同时仍然保留其先前位置的副本。

Here是一个很好的表,它清楚地呈现了不同迭代器概念之间的关系。

当然有人可能会争辩说调用者应该知道InputIterator的工作原理,并且应该允许他们方便地选择适合他们当前需要的版本。 dyp在评论部分提供了此类问题的示例:http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#2353

然而,取悦所有人总是会导致界面中方法数量激增。

该链接表明现在的状态是一种共识的状态。