【问题标题】:How come some libstdc++ iterators have operator++ but no operator+?为什么有些 libstdc++ 迭代器有 operator++ 而没有 operator+?
【发布时间】:2016-03-15 21:05:16
【问题描述】:
我刚刚注意到对于迭代器类 std::__detail::_Node_iterator(在 GCC 的 libstdc++ 中,源代码 here),我们有一个 operator++() 但没有 operator+(),所以你可以使用 (my_set.cbegin()++)++ 但你不能使用my_set.cbegin() + 2.
这是为什么呢?只是缺少语法糖还是有更深层次的原因?
【问题讨论】:
标签:
c++
iterator
operators
containers
c++-standard-library
【解决方案1】:
标准没有提供operator+,当它是 O(n) 时,会令许多用户感到惊讶。
它确实提供了一个可以使用的功能std::advance,如果你准备支付费用的话。
【解决方案2】:
这是为什么呢?只是缺少语法糖还是有更深层次的原因?
理解这对我来说可能有点推测(我没有设计/实现迭代器),我的想法是迭代器旨在以某种程度的安全遍历集合。编写iterator++ 之类的内容会安全地将您从集合中的现有元素带到下一个元素,或者如果您已到达末尾,则自动指向null。
它也比写iterator = iterator + 1 或iterator += 1 更短,这可能是将其限制为仅++ 的关键原因。添加所有这些似乎是多余且不必要的。
引用C++ Reference(我的重点)
迭代器是指向某个范围内的某个元素的任何对象
元素(如数组或容器),具有迭代能力
使用一组运算符(with at
最少增量(++)和取消引用(*)运算符)。
基于此,将客户端对实现迭代器的要求保持在最低限度似乎是一个有意的架构决策。请注意,根据上述措辞(即“至少”),似乎没有技术原因说明为什么有人无法添加对其他运算符的支持,包括!= 以外的比较运算符.他们是否应该可能是另一个讨论。
此外,迭代器通常会按顺序遍历某个范围内的所有对象,因此从这个意义上说,允许iterator + X 似乎违背了它的预期目的。
例如,如果您执行iterator + 2,您怎么知道您要求的不超过集合从迭代器当前位置真正剩下的东西?您可能试图越过集合的末尾并等待分段错误——或者他们需要开始抛出异常。迭代器安全遍历集合而不超出范围的能力是你在这里失去的好处,恕我直言。
迭代器仅用于保护客户端免受集合的实现细节的影响。也就是说,客户端不需要知道集合是实现为数组、某种链表还是某种树。它也不需要计算集合有多少项目,这再次使它更容易实现和使用。 (它有一个单一的职责。)
基于此,并牢记之前的“安全”和简约要求细节,避免实现对象可以支持的所有可能运算符的决定对我来说是有意义的。