2015-06-21 59 views
4

目前,std::advance是这样设计的:为什么不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确实会返回结果迭代器。

+5

我相信这个设计需要支持输入迭代器。 'std :: next'和'std :: prev'需要相应的前向和双向迭代器。 –

+0

我相信他们没有想到像这样设计它......就像很多其他的东西一样。 – Nawaz

+0

IDK。但是,在其他地方,我们做了一些努力来避免迭代器的多余副本,例如post和pre increment。所以显然有人认为这是一个性能问题,正如你所建议的那样。 –

回答

1

没有任何技术原因阻止它将参考返回到输入值,任何合理的编译器都应该能够优化返回值,如果不使用它。所以他们可以这样做,如果他们想的话。

我觉得自己的选择是有道理的从API设计的角度来看,虽然 - std::prevstd::next采取迭代器,并返回不同的迭代器,指向上一个或下一个元素,分别无需修改输入

std::advance另一方面修改输入。如果它返回了对输入迭代器的引用,那么它可能会对返回副本而不就地修改输入的函数感到困惑。这可能是危险的。

注意std::advance作品与InputIterator s,这包括迭代器,其中迭代有副作用(的东西,如从流读取的迭代器),但std::prevstd::next只有ForwardIterator s,这没有副作用的工作。

于是久违的独立(如std::prevstd::next)将是一个糟糕的主意 - 你最终与同流两个迭代器,这可能会影响彼此不利。

+0

作为一个解释,这没有意义 - 你只是重复明显的事实。整个答案归结为“他们可以做到,但他们没有”。 – BartoszKP

+0

@BartoszKP他们可以做到这一点,但他们不这样做,因为这不是一个好主意。我的回答解释了为什么它会是一个坏主意。 – AaronI

+0

例如,第三段是适用于* any *函数的小事,不仅是'std :: advance'。如果'std :: prev'引用了一个引用,你可以说完全一样的东西 - 返回一个引用可能会被一个函数搞糊涂,该函数返回拷贝而不修改输入。只有关于输入和前向迭代器(*,你刚刚添加*)的段落是相关的。所以,现在看起来好了(虽然我会删除所有其他部分,因为他们只是噪音,很难找到点,这只是在第4段) - 我会删除我的意见。干杯! – BartoszKP

0

的主要原因,如在评论部分表示的是一个InputIterator并不保证增量迭代后,以前的任何迭代器仍然有效:

InputIterators只保证有效期为单通道算法:一旦InputIterator i被增加,其先前值的所有副本都可能失效。

因此,如果std::advance返回副本,调用者可能会以两个迭代器结束,其中一个可能无效。带引用的接口表明这不是应该如何使用输入迭代器。

在另一方面std::prevstd::next采取BidirectionalIterator,其中除其他外,要满足ForwardIterator要求:

不同于InputIterator的和输出迭代,可以在多遍算法中使用。

所以,你可以移动一个迭代器,同时仍然保存它以前的位置的副本。

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


当然,人们可能会认为,主叫方应该知道InputIterator的是如何工作的,应当允许有选择适合自己当前需要一个版本的方便。 dyp在评论部分提出了一个这样的问题的例子:http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#2353

然而,每个人都喜欢,总是会导致界面中方法的数量激增。

该链接表明,现在是一种即将形成共识的状态。

+1

请参阅http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#2353 – dyp

相关问题