【问题标题】:Why isn't a reverse iterator a formal iterator category according to the C++17 standard?根据 C++17 标准,为什么反向迭代器不是正式的迭代器类别?
【发布时间】:2019-03-18 17:07:41
【问题描述】:

反向迭代器不在迭代器类别标签列表中,因此假定它不是类别。那么究竟是什么呢?

【问题讨论】:

  • 为什么需要一个标签?迭代器的 user 是否为反向迭代器都没有区别。有些迭代器甚至根本没有方向。
  • 我想我的主要问题是反向迭代器究竟被归类为什么。虽然我现在不需要这样的标签,但我可以设想您可能希望以不同顺序遍历的数据结构(例如出于缓存局部性目的),具体取决于您是前进还是后退。

标签: c++ stl c++17


【解决方案1】:

迭代器类别编码功能级别

  • 输入迭代器是最低限度的 - 可递增和可取消引用一次
  • 前向迭代器是一种输入迭代器,您可以多次取消引用并支持多遍。
  • 双向迭代器是可以递减的正向迭代器
  • 随机访问迭代器是一个双向迭代器,您可以 O(1) 前进 +/- n
  • 连续迭代器是一种随机访问迭代器,它引用连续内存

算法使用这些级别的功能 - 一些算法需要特定级别的功能,一些算法可以简单地基于特定级别的功能进行优化(例如,advance(it, n) 用于随机访问迭代器可以只是做it += n 而对于前向迭代器它必须是++it 在循环中)。

但“反转”不是一种功能级别 - 它只是呈现基础数据的一种不同方式。反向迭代器不值得拥有自己的迭代器类别,原因与“移动”迭代器不适合或“过滤”迭代器不适合或“计数”迭代器不适合的原因相同。算法不关心迭代器是否反转——它们的工作方式相同。 ++it 实际移动迭代器的方式并不重要。

反向迭代器只是迭代器。 std::reverse_iterator 被称为迭代器适配器(以及其他一些,比如std::move_iterator)——它是一个适应不同迭代器的迭代器。但是你可以编写一个不是适配器的反向迭代器——事实上,你甚至可以编写一个不是双向的反向迭代器!这两个概念是正交的。

【讨论】:

  • "连续迭代器是指连续内存的随机访问迭代器" Range 系统有效地将连续迭代器定义为可以转换(通过函数)的随机访问迭代器进入覆盖相同范围的value_type*s。这意味着它们指的是连续数组的某些部分。
  • @Nicol 不知道你从哪里得到的。直接指定ContiguousIterator 引用连续内存。转换为value_type*addressof(*it)
  • 当我说“有效”时,我的意思是指实际上可以通过概念检测的东西,而不是由于标签而假设的东西。双向意味着能够做到--。等效的行为差异是转换为指针,即 ContiguousRange 要求您可以对其应用 range::data 的方式。但是,我认为 to_address 在最近的会议上已被 C+20 中的 ContiguousIterators 采用,但显然不是。
【解决方案2】:

所以假设它不是一个类别。

你的假设是正确的。反向迭代器不是迭代器的一个类别。

那么它到底是什么?

标准将std::reverse_iterator 定义为:

类模板 reverse_iterator 是一个迭代器适配器,从定义的序列的末尾开始迭代 通过其底层迭代器到该序列的开头。反向之间的基本关系 迭代器及其对应的迭代器 i 由恒等式建立: &(reverse_iterator(i)) == &(i - 1).

std::reverse_iterator<Iterator>的迭代器类别是Iterator的迭代器类别。


同样,其他迭代器适配器,例如移动迭代器、过滤迭代器、跨步迭代器等也不是迭代器类别。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-11-14
    • 1970-01-01
    • 2010-10-27
    • 2016-04-20
    • 1970-01-01
    • 1970-01-01
    • 2011-01-19
    • 2018-03-20
    相关资源
    最近更新 更多