+-- 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()
来自他们的反向同行?
但是如果我有两个反向迭代器 rit1
和 rit2
定义范围 (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/