2

我有以下代码:

int main()
{
    vector<int> v;

    for(int i = 0; i < 10; ++i)
        v.push_back(i);

    auto it = v.begin() + 3;

    cout << "Iterator: " << *it << endl;

    vector<int>::reverse_iterator revIt(it);

    cout << "Reverse iterator: " << *revIt << endl;

}

运行此代码后,我得到以下输出:

Iterator: 3
Reverse iterator: 2

有人可以解释为什么这两个值不同吗?

4

4 回答 4

6

反向迭代器“对应”到具有base一个元素偏移量的迭代器,因为如何rbegin()并且rend()必须使用有效的基本迭代器(end()begin()分别)来表示。例如,rend()不能用“指向”容器迭代器之前的begin()迭代器来表示,尽管它在逻辑上是这样表示的。所以rend()'基础迭代器'是begin(). 因此,rbegin()的基迭代器变为end()。反向迭代器在取消引用时会自动调整该偏移量(使用*or->运算符)。

Scott Meyers的一篇旧文章详细解释了这种关系以及一张漂亮的图片:

准则 3:了解如何使用 reverse_iterator 的基本迭代器

在 reverse_iterator 上调用基成员函数会产生“对应的”迭代器,但不清楚这意味着什么。例如,看一下这段代码,它将数字 1-5 放入向量中,将 reverse_iterator 设置为指向 3,并将迭代器设置为 reverse_iterator 的基数:

vector<int> v;

// put 1-5 in the vector
for (int i = 1; i <= 5; ++i) {
  v.push_back(i);
}

// make ri point to the 3
vector<int>::reverse_iterator ri =
  find(v.rbegin(), v.rend(), 3);

// make i the same as ri's base
vector<int>::iterator i(ri.base());

执行此代码后,可以认为是这样的:

替代文字

这张图很好,显示了 reverse_iterator 的特征偏移量及其相应的基本迭代器,它模仿了 rbegin() 和 rend() 相对于 begin() 和 end() 的偏移量,但它并没有告诉你你需要的一切要知道。特别是,它没有解释如何使用 i 来执行您想在 ri 上执行的操作。

于 2012-04-29T16:44:31.743 回答
4

看起来文档说他们这样做是为了处理过去的元素,即如果你反转一个过去的迭代器,新的反向迭代器指向最后一个元素。

于 2012-04-29T16:28:17.350 回答
2

24.5.1 反向迭代器的第一段说:

类模板 reverse_iterator 是一个迭代器适配器,它从其底层迭代器定义的序列的末尾迭代到该序列的开头。反向迭代器与其对应的迭代器 i 之间的基本关系由恒等式建立:
&*(reverse_iterator(i)) == &*(i - 1)

返回的值rend()不能指向 before begin(),因为那是无效的。所以决定rend()应该包含的值begin()和所有其他反向迭代器进一步移动一个位置。对此operator*进行补偿并无论如何访问正确的元素。

于 2012-04-29T16:43:45.317 回答
1

反向迭代器看起来总是“前一个”然后是前向,因为它的范围移动了一个:

前向迭代器从 begin() (第一个元素)到 end() (过去最后一个:[begin-end) 在末尾打开)

反向迭代器根据定义从rbegin() { return reverse_iterator(end()); }to 开始rend() { return reverse_iterator(begin()); },但也必须遍历开放范围 [rbegin-rend),其中 rbegin 是最后一个(不是“过去最后一个”),并且是“在第一个之前”(不是“第一个” ) 因此要容纳 1 个差异。

于 2012-04-29T16:52:07.000 回答