递增可变输入迭代器是否会使旧迭代器值失效
Does incrementing a mutable input iterator invalidate old iterator values?
进一步满足输出迭代器要求的迭代器称为可变迭代器。不可变迭代器称为常量迭代器。[24.2.1:4]
这表明您可以有一个可变的输入迭代器,它同时满足输入和输出迭代器的要求。
递增输入迭代器后,其旧值的副本不需要可取消引用 [24.2.3]。但是,该标准对输出迭代器没有说同样的话;事实上,后缀增量的操作语义是{ X tmp = r; ++r; return tmp; }
给出的,这表明输出迭代器可能不会使旧的迭代器值无效(副本)。
那么,递增可变输入迭代器会使旧的迭代器副本失效吗?
如果是这样,您将如何支持带有(例如)代理对象的X a(r++); *a = t
或X::reference p(*r++); p = t
等代码?
如果不是,那么为什么boost::iterator
声称它需要一个代理对象?(链接是代码;向下滚动以阅读struct
writable_postfix_increment_proxy
和postfix_increment_result
的评论)。也就是说,如果可以返回旧迭代器值的(可取消引用)副本,为什么需要将此副本包装在代理中?
如果在下一节中找到解释,[24.2.5] 前向迭代器,其中说明了它们与输入和输出迭代器的不同之处:
在以下情况下,
a
和X
类型的b
两个可取消引用迭代器提供多通道保证:—
a == b
意味着++a == ++b
和
—X
是指针类型,或者表达式(void)++X(a), *a
等效于表达式*a
。[ 注意:
a == b
意味着++a == ++b
的要求(对于输入和输出迭代器来说并非如此)以及通过可变迭代器(适用于输出迭代器)消除对赋值数量的限制允许使用带有前向迭代器的多通道单向算法。 —尾注 ]
不幸的是,标准必须作为一个整体来阅读,并且解释并不总是在您期望的地方。
输入和输出迭代器基本上设计为允许单通道遍历:描述每个元素只能访问一次的序列。
流就是一个很好的例子。如果您从 stdin 或套接字读取,或写入文件,则只有流的当前位置。当您递增迭代器时,指向同一基础序列的所有其他迭代器都将失效。
前向迭代器允许多遍遍历,这是您需要的额外保证:它们确保您可以复制迭代器,递增原始迭代器,并且副本仍将指向旧位置,因此您可以从那里进行迭代。
- std::vector::erase() 真的会在擦除时使迭代器失效吗?
- 没有迭代器失效是否意味着推进迭代器的有效性?
- C++11 std::列出拼接后的迭代器失效
- C++ std::map 和 std::set 擦除复制值,从而使迭代器失效
- 当没有迭代器失效时,这是否包括结束迭代器?
- std::map 线程安全和迭代器失效
- 赋值(运算符 =)使容器的迭代器失效
- std::list<>::splice 使迭代器失效。理由?
- C++11 中的过去终结迭代器失效
- 在字符串中使用 erase 函数是否会使迭代器失效
- tbb::concurrent_unordered_map::unsafe_erase 是否会使任何现有迭代器失效
- 迭代器失效 - end() 是否算作迭代器
- C++ deque:当迭代器失效时
- Unordered_map迭代器失效
- C++函数从列表中查找最小值.此函数是否正确,因为返回的迭代器失效
- 这是正确的行为吗?std::map 迭代器失效
- c++ multimap迭代器失效
- 如果STL容器中的迭代器失效,指针是否也会失效?
- 迭代器失效规则意味着线程安全吗?
- 为什么Vector中的Erase和Insert函数使迭代器失效?