rend指向哪里?

时间:2010-12-05 09:42:15

标签: c++ pointers stl vector iterator

为了支持STL的半开放范围的概念,我们可以指向数组的一个接一个的结尾。假设我们有一个三元素的向量。如果将std::vector::iterator实现为指针(通常是发布版本中的情况),则beginend指向这些位置:

    +---+---+---+....
    |   |   |   |   .
    +---+---+---+....
      ^           ^
    begin        end

其中点表示一个过去的结束伪元素。既然没有一个在开头之前的东西,那么rend究竟指向哪里?让我来说明一下:

    +---+---+---+....
    |   |   |   |   .
    +---+---+---+....
  ^           ^
rend       rbegin

显然,插图是错误的,因为rend是非法指针。所以我想std::vector::reverse_iterator的实现永远不会成为指针,即使在发布版本中也是如此。

我是对的吗?那么实施reverse_iterator的最有效方法是什么?

5 个答案:

答案 0 :(得分:5)

因为不允许取消引用指向容器外部的迭代器,所以rend()“指向”实际上并不重要。它不必是合法的指针值,它可以是对容器/迭代器类型具有特定含义的任何值。

答案 1 :(得分:5)

rbegin的结果与end相同(结尾一个),rend的结果与begin相同(第一项) )。当取消引用反向迭代器时,它将返回对范围中前一项的引用。

答案 2 :(得分:3)

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()对象,则基本迭代器指向结束的一个,但取消引用反向迭代器将为您提供最后一个元素。没有伤害。

答案 3 :(得分:2)

std::reverse_iterator接口包含.base成员函数,该函数检索与原始迭代器相等的迭代器。我怀疑他们通常做的只是缓存原始迭代器,并在operator * overload中偏移1。

答案 4 :(得分:1)

其他答案很好地回答了这个问题。

但是我也想知道它是否合法,因为假设一个实现可以在幕后做任何事情,只要它能够工作并符合标准。如果它选择将迭代器作为指针实现并选择取消引用,那么编译器有责任知道这将起作用。您无法以这种方式自己实现它,但在我看来,编译器作者有特殊许可来执行此操作,因为他们知道未定义的行为将是什么,并且不会直接将这种行为暴露给您,只是通过迭代器接口。