为了支持STL的半开放范围的概念,我们可以指出数组的一个接一个的结尾。假设我们有一个三元素的向量。如果 std::vector::iterator
实现为指针,就像发布版本中的情况一样 begin
和 end
指向这些位置:
+---+---+---+....
| | | | .
+---+---+---+....
^ ^
begin end
点表示一个过去的结束伪元素。因为没有像开始之前那样的东西,究竟会在哪里 rend
指向?让我说明一下:
+---+---+---+....
| | | | .
+---+---+---+....
^ ^
rend rbegin
显然,插图是错误的,因为 rend
是一个非法的指针。所以我想实施 std::vector::reverse_iterator
永远不会成为指针,即使在发布版本中也是如此。
我对吗?什么是最有效的实施方式 reverse_iterator
然后?
什么是什么之间的区别 reverse_iterator
逻辑上指向它包含的迭代器指向的内容。从逻辑上讲, rbegin
产生一个指向序列的最后一个元素的迭代器 rend
产生一个迭代器,指向开始前的一个元素。但这通常使用一个基本迭代器实现,该迭代器指向反向迭代器指向的元素之后的一个元素。像这样的东西:
template<class Iter>
class reverse_iter
{
Iter base;
public:
explicit reverse_iter(Iter it) : base(it) {}
reference operator*() const {
Iter tmp = base;
--tmp;
return *tmp;
}
reverse_iter& operator++() {--base; return *this;}
};
所以,如果你初始化这样的 reverse_iter<>
对象 container.end()
基本迭代器指向一个结束但是反向引用反向迭代器将为您提供最后一个元素。没有伤害。
因为您不允许取消引用指向容器外部的迭代器,所以实际上并不重要 rend()
“指着。它不一定是合法的 指针 value,它可以是对容器/迭代器类型具有特定含义的任何值。
什么是什么之间的区别 reverse_iterator
逻辑上指向它包含的迭代器指向的内容。从逻辑上讲, rbegin
产生一个指向序列的最后一个元素的迭代器 rend
产生一个迭代器,指向开始前的一个元素。但这通常使用一个基本迭代器实现,该迭代器指向反向迭代器指向的元素之后的一个元素。像这样的东西:
template<class Iter>
class reverse_iter
{
Iter base;
public:
explicit reverse_iter(Iter it) : base(it) {}
reference operator*() const {
Iter tmp = base;
--tmp;
return *tmp;
}
reverse_iter& operator++() {--base; return *this;}
};
所以,如果你初始化这样的 reverse_iter<>
对象 container.end()
基本迭代器指向一个结束但是反向引用反向迭代器将为您提供最后一个元素。没有伤害。
因为您不允许取消引用指向容器外部的迭代器,所以实际上并不重要 rend()
“指着。它不一定是合法的 指针 value,它可以是对容器/迭代器类型具有特定含义的任何值。
的结果 rbegin
指向相同 end
(一个结束),结果 rend
与...相同 begin
(第一项)。取消引用反向迭代器时,它将返回对范围中上一项的引用。
该 std::reverse_iterator
界面包括一个 .base
检索与原始迭代器相等的迭代器的成员函数。我怀疑他们通常做的只是缓存原始迭代器,并在operator * overload中偏移1。
其他答案很好地回答了这个问题。
但我也想知道它是否合法,因为假设一个实现可以在幕后做任何事情,只要它能够工作并符合标准。如果它选择将迭代器实现为指针并选择取消引用那么编译器有责任知道这将起作用。您无法以这种方式自己实现它,但在我看来,编译器作者有特殊许可来执行此操作,因为他们知道未定义的行为将是什么,并且不会直接将这种行为暴露给您,只是通过迭代器接口。