为什么不std :: advance返回结果迭代器?
目前,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::next
和std::prev
确实会返回结果迭代器。
没有任何技术原因阻止它将参考返回到输入值,任何合理的编译器都应该能够优化返回值,如果不使用它。所以他们可以这样做,如果他们想的话。
我觉得自己的选择是有道理的从API设计的角度来看,虽然 - std::prev
和std::next
采取迭代器,并返回不同的迭代器,指向上一个或下一个元素,分别无需修改输入。
std::advance
另一方面修改输入。如果它返回了对输入迭代器的引用,那么它可能会对返回副本而不就地修改输入的函数感到困惑。这可能是危险的。
注意std::advance
作品与InputIterator
s,这包括迭代器,其中迭代有副作用(的东西,如从流读取的迭代器),但std::prev
和std::next
只有ForwardIterator
s,这没有副作用的工作。
于是久违的独立值(如std::prev
和std::next
)将是一个糟糕的主意 - 你最终与同流两个迭代器,这可能会影响彼此不利。
作为一个解释,这没有意义 - 你只是重复明显的事实。整个答案归结为“他们可以做到,但他们没有”。 – BartoszKP
@BartoszKP他们可以做到这一点,但他们不这样做,因为这不是一个好主意。我的回答解释了为什么它会是一个坏主意。 – AaronI
例如,第三段是适用于* any *函数的小事,不仅是'std :: advance'。如果'std :: prev'引用了一个引用,你可以说完全一样的东西 - 返回一个引用可能会被一个函数搞糊涂,该函数返回拷贝而不修改输入。只有关于输入和前向迭代器(*,你刚刚添加*)的段落是相关的。所以,现在看起来好了(虽然我会删除所有其他部分,因为他们只是噪音,很难找到点,这只是在第4段) - 我会删除我的意见。干杯! – BartoszKP
的主要原因,如在评论部分表示的是一个InputIterator并不保证增量迭代后,以前的任何迭代器仍然有效:
InputIterators只保证有效期为单通道算法:一旦InputIterator i被增加,其先前值的所有副本都可能失效。
因此,如果std::advance
返回副本,调用者可能会以两个迭代器结束,其中一个可能无效。带引用的接口表明这不是应该如何使用输入迭代器。
在另一方面std::prev
和std::next
采取BidirectionalIterator,其中除其他外,要满足ForwardIterator要求:
不同于InputIterator的和输出迭代,可以在多遍算法中使用。
所以,你可以移动一个迭代器,同时仍然保存它以前的位置的副本。
Here是一个很好的表格,清楚地表示了不同迭代器概念之间的关系。
当然,人们可能会认为,主叫方应该知道InputIterator的是如何工作的,应当允许有选择适合自己当前需要一个版本的方便。 dyp在评论部分提出了一个这样的问题的例子:http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#2353。
然而,每个人都喜欢,总是会导致界面中方法的数量激增。
该链接表明,现在是一种即将形成共识的状态。
请参阅http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#2353 – dyp
我相信这个设计需要支持输入迭代器。 'std :: next'和'std :: prev'需要相应的前向和双向迭代器。 –
我相信他们没有想到像这样设计它......就像很多其他的东西一样。 – Nawaz
IDK。但是,在其他地方,我们做了一些努力来避免迭代器的多余副本,例如post和pre increment。所以显然有人认为这是一个性能问题,正如你所建议的那样。 –