c++ - 为什么 reverse_iterator::base 偏移量?

标签 c++ stl iterator language-lawyer reverse-iterator

      +-- v.begin()           +-- v.end()
      |                       |
      v                       v
    +---+---+---+---+---+---+ - +
    | o | o | o | o | o | o | x |
    +---+---+---+---+---+---+ - +

+ - +---+---+---+---+---+---+
| x | o | o | o | o | o | o |
+ - +---+---+---+---+---+---+
  ^                       ^
  |                       |
  +-- v.rend()            +-- v.rbegin()

(ASCII 从 this answer 复制和编辑,这实际上促使我问现在的问题。)

我确实看到了 &*rit == &*(rit.base() - 1) 的优势, 因为这样我可以拿 rit.base()对于任何反向迭代器 rit而且我总能得到一个有效的迭代器。

但同时

  • 我无法取消引用 v.rbegin().base() ;我得记得先减1,*(v.rbegin().base() - 1) ,
  • 而且我不能取消引用 v.rend().base() - 1正是因为我无法取消引用 v.rend() .

如果设计是 &*rit == &*rit.base() 会怎么样? ?

  • 我们无法调用 v.rend().base() ,是的,但这仅对应于无法取消引用 v.rend().base() - 1在当前设计中;
  • 我们无法获得 v.end()直接来自反向迭代器,甚至不是最近的迭代器,b.rbegin() , 但那只是到 - 1我们必须添加到 rit.base()在当前的设计中,获得指向与反向相同元素的正向迭代器。

我的意思是,在我看来,设计决策是否是 &*rit == &*(rit.base() - 1) (原样)或那个&*rit == &*rit.base() ,我们会有同样多的便利

  • rit.base()在实际设计中总是可以的,
  • - 1在替代设计中通常不需要

和不便

  • 无法取消引用所有有效的 rit.base()在实际设计中,
  • 需要+1 v.rbegin()得到v.end()在替代设计中,

只是在相反的情况下。

所以我的问题是:做出确实已经做出的选择是否有明确的优势?还是只是抛硬币?


我看到第一个元素之前没有有效的迭代器,但这就是我的观点。当引入反向迭代器时,制作 std::prev(v.begin()) 会出现什么问题?一个有效的、不可取消引用的迭代器,就像 v.end()


事后看来,我确实看到了一个毋庸置疑的优势。

没看出v.rbegin().base() == v.end()的优势/v.rend().base() == v.begin()因为我为什么要创建 v.end()/v.begin()来自他们的反向同行?

但是如果我有两个反向迭代器 rit1rit2定义范围 (rit1, rit2] , 然后取 it1 = rit1.base()it2 = rit2.base()允许在相反方向轻松引用相同范围的元素,[it1, it2) .

长话短说:_我应该先阅读 The C++ Standarl Library - 2nd ed. 中的 §9.4.1。

最佳答案

这不是设计决定,而是必然。

反向迭代器并不是某种能够以某种方式反向迭代范围的神奇事物。它是建立在已经存在的事物之上的外观。

当您有一个包含 6 个条目的集合(如您的图片所示)时,您所拥有的只是 7 个可用的迭代器值,仅此而已(6 个是可取消引用的,一个是结束迭代器值)。这就是反向迭代器可以构建的全部内容。

因为没有先行迭代器(就像第二张图让人想到的那样),除了将 rbegin() 映射到 之外,对于反向迭代器没有其他选择>end()rend()begin()。也就是说,您有 (rbegin() + i).base() == end() - i

这反过来又要求可取消引用的迭代器(从 rbegin() 开始的前 6 个)实际上必须取消引用迭代器 .base()-1。没有其他方法可以实现反向迭代器。

关于c++ - 为什么 reverse_iterator::base 偏移量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71366118/

相关文章:

c++ - 网格面三角形的纵横比

c++ - bind() 用于将成员函数用作 STL 比较函数

c++ - 将列表导出到文件时重复写入列表的最后一个对象

c++ - 无法增加 Glib::ustring::iterator(出现 "invalid lvalue in increment"编译器错误)

java - 在 for 循环中嵌套 string.splits - 分配时内部 split 得到 NPE

c++ - 在变量 C++ 周围使用大括号(大括号)

c++ - CMake如何强制third_party库在当前项目源目录中包含项目文件?

c++ - CRect 和 CRect* 如何成为 GetClientRect 的输入参数?

C++ 为什么atomic_load的参数类型是指针而不是引用?

c++ - C++ 中的 vector 不响应一种方法但对其他方法很好