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

Why does not std::advance return the resulting iterator?

本文关键字:迭代器 std advance 为什么 返回      更新时间:2023-10-16

目前,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 确实返回生成的迭代器。

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

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

另一方面,std::advance修改输入。如果它返回了对输入迭代器的引用,则可能会将其与返回副本而不就地修改输入的函数混淆。这可能很危险。

请注意,std::advance适用于 InputIterator s,其中包括迭代器,其中迭代有副作用(例如从流中读取的迭代器),但std::prevstd::next仅适用于没有副作用的ForwardIterator

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

如注释部分所示,主要原因是 InputIterator 不保证在增加迭代器后,任何以前的迭代器仍然有效:

输入迭代

器仅保证单次传递算法的有效性:一旦输入迭代器 i 递增,其先前值的所有副本都可能失效。

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

另一方面,std::prevstd::next采用双向迭代器,它满足前向迭代器的要求:

与输入迭代器和输出迭代器不同,它可以用于多遍算法。

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

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


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

然而,取悦每个人总是会导致界面中方法数量的爆炸式增长。

这种联系表明,现在的情况是有待达成共识的状态。