rend指向哪里?

发布于 2024-10-06 02:26:07 字数 655 浏览 1 评论 0原文

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

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

其中的点表示最后一个伪元素。既然不存在“一开始之前的事”这样的东西,那么 rend 到底会指向哪里呢?让我举例说明:

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

显然,这个说明是错误的,因为 rend 是一个非法指针。所以我猜想 std::vector::reverse_iterator 的实现永远不可能是指针,即使在发布版本中也是如此。

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

To support STL's notion of half-open ranges, we are allowed to point one-past-the-end of an array. Suppose we have a vector of three elements. If std::vector::iterator is implemented as a pointer, as is usually the case in release builds, then begin and end point to these locations:

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

Where the dots denote the one-past-the-end pseudo-element. Since there is no such thing as a one-before-the-beginning, where exactly would rend point to? Let me illustrate:

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

Clearly, the illustration is wrong, because rend is an illegal pointer. So I guess the implementation of std::vector::reverse_iterator can never be a pointer, even in release builds.

Am I right? What would be the most efficient way of implementing reverse_iterator then?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

野却迷人 2024-10-13 02:26:07

rbegin 的结果指向与 end 相同(超过末尾),rend 的结果指向与 相同开始(第一项)。当反向迭代器被取消引用时,它返回对范围中前一项的引用。

The result of rbegin points to the same as end (one past the end), and the result of rend to the same as begin (the first item). When a reverse iterator is dereferenced, it returns a reference to the previous item in the range.

獨角戲 2024-10-13 02:26:07

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

Because you're not permitted to dereference an iterator that points outside the container, it doesn't actually matter what rend() "points" to. It doesn't have to be a legal pointer value, it can be any value that has a particular meaning to the container/iterator type.

红焚 2024-10-13 02:26:07

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;}
};

因此,如果您使用 container.end() 初始化这样一个 reverse_iter<> 对象,则基本迭代器指向末尾的一个,但取消引用反向迭代器会给你最后一个元素。没有造成任何伤害。

There is a difference between what a reverse_iterator points to logically and what its contained iterator points to. Logically, rbegin yields an iterator that points to the last element of the sequence and rend yields an iterator that points to one element before the start. But this is usually implemented with a base iterator which points to the next location after the location the reverse iterator is pointing to. Something like this:

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;}
};

So, if you initialize such a reverse_iter<> object with container.end(), the base iterator points one past the end, but dereferencing the reverse iterator will give you the last element. No harm done.

可遇━不可求 2024-10-13 02:26:07

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

The std::reverse_iterator interface includes a .base member function that retrieves an iterator equal to the original. I suspect that what they usually do is just cache the original iterator, and offset by 1 in the operator* overload.

鹤舞 2024-10-13 02:26:07

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

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

The other answers answer the question well.

But I also wonder if it would be legal anyway, as presumably an implementation can do whatever it likes behind the scenes as long as it works and meets the standards. If it chooses to implement the iterator as a pointer and chooses to dereference that then it's the compilers responsibility to know that that will work. You wouldn't be able to implement it this way yourself but it seems to me that the compiler author has special license to do this as they know what the undefined behavour will be, and don't expose that behavour to you directly, just through an iterator interface.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文