【问题标题】:Iterator value differs from reverse iterator value after conversion迭代器值与转换后的反向迭代器值不同
【发布时间】:2012-05-09 13:36:44
【问题描述】:

我有以下代码:

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

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

【问题讨论】:

  • 我不是 100% 确定,但是正向迭代器会向前看,而反向迭代器会向后看。 v = {1, 2, * 3, 4...} 其中 * 是它们两个的迭代器位置。看看他们往哪个方向走。
  • @chris: 不完全是:或者更好,这就是 java 定义迭代器的方式(指向“中间”) C++ 有不同的概念。但实际结果也符合你的解释。但是是结果,而不是定义。
  • @EmilioGaravaglia,感谢您清理它。这不是我很熟悉的东西。

标签: c++ stl iterator


【解决方案1】:

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

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

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

【讨论】:

    【解决方案2】:

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

    一位老article by 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 上表演。

    【讨论】:

      【解决方案3】:

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

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

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

      【讨论】:

        【解决方案4】:

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

        【讨论】:

          猜你喜欢
          • 2010-10-27
          • 1970-01-01
          • 2011-01-03
          • 2020-11-06
          • 1970-01-01
          • 2013-12-03
          • 2010-12-19
          • 2013-02-07
          相关资源
          最近更新 更多