为什么 std::advance 不返回生成的迭代器
Why does not std::advance return the resulting iterator?
目前,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
。
因此,返回一个单独的值(如 std::prev
和 std::next
)将是一个坏主意 - 您最终会在同一流上得到两个迭代器,这可能会相互产生不利影响。
如注释部分所示,主要原因是 InputIterator 不保证在增加迭代器后,任何以前的迭代器仍然有效:
输入迭代器仅保证单次传递算法的有效性:一旦输入迭代器 i 递增,其先前值的所有副本都可能失效。
因此,如果std::advance
返回副本,则调用方最终可能会得到两个迭代器,其中一个可能无效。带有引用的接口指示这不是输入迭代器应使用的方式。
另一方面,std::prev
和std::next
采用双向迭代器,它满足前向迭代器的要求:
与输入迭代器和输出迭代器不同,它可以用于多遍算法。
因此,您可以在移动迭代器的同时仍保留其先前位置的副本。
这是一个不错的表格,清楚地显示了不同迭代器概念之间的关系。
当然,有人可能会争辩说,调用者应该了解InputIterator的工作原理,并且应该允许他们方便地选择适合其当前需求的版本。dyp在评论部分提供了此类问题的一个例子:http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#2353。
然而,取悦每个人总是会导致界面中方法数量的爆炸式增长。
这种联系表明,现在的情况是有待达成共识的状态。
- 使用std::multimap迭代器创建std::list
- 来自 std::list 的迭代器 .end() 按预期返回"0xcdcdcdcdcdcdcdcd"但 .begin()
- 如何在c++迭代器类型中包装std::chrono
- std::vector::迭代器是否可以合法地作为指针
- 为什么 C++ std::unordered_map 从 emplace/ 找到返回一个迭代器?
- 如何在创建自定义迭代器时获得 std::p air 的第一个和第二个?
- 修改 std::vector 会使迭代器无效吗?
- std::list 中的迭代器感知对象
- 迭代器库中的 std::size() 不适用于传递给函数的 C 样式数组
- C++如何乘以包含 std::variant 元素的向量的迭代器?正在执行迭代器类型的转换?
- 为什么范围算法与 std 的迭代器不兼容?
- 从 std::vector 迭代器中执行函数指针
- 无法获得等效的 std::less 来用于嵌套迭代器
- 再次获得 std::map 会更改之前的迭代器
- 为什么"std::uninitialized_copy"通常取消对未初始化内存的迭代器的引用不是未定
- 创建可以遍历 std::map 值的通用模板迭代器的最简单方法是什么?
- 矢量迭代器不能与 std::shared_ptr<> 取消引用
- 比较未引用的映射迭代器(std::pairs):C2678
- STL迭代器std::distance()错误
- ->秒是否为迭代器 std::map::end()?