【问题标题】:Is a reverse iterator constructed from an iterator is its previous iterator?从迭代器构造的反向迭代器是它的前一个迭代器吗?
【发布时间】:2020-01-21 21:48:56
【问题描述】:

https://en.cppreference.com/w/cpp/iterator/reverse_iterator 上说:

std::reverse_iterator 是一个迭代器适配器,它可以反转给定迭代器的方向。换句话说,当提供双向迭代器时,std::reverse_iterator 会生成一个新迭代器,该迭代器会从底层双向迭代器定义的序列的末尾移动到开头。

对于从迭代器i 构造的反向迭代器r,关系&*r == &*(i-1) 始终为真(只要r 是可解引用的);因此,从一个过去的迭代器构造的反向迭代器取消对序列中最后一个元素的引用。

所以我尝试了这段代码以了解更多信息:

int main() {


    std::deque<int> di{ 1, 1, 2, 3, 5, 8, 13 }; // fibonacci series
    // deque has bi-directional iterators

    std::deque<int>::iterator offEnd = di.end(); // one-past the last element in di
    std::deque<int>::reverse_iterator r(offEnd); // constructing a reverse iterator from an iterator from deque<int> di

    std::cout << &offEnd << " : " /*<< *r */ << std::endl;
    std::cout << &(offEnd - 1) << " : " << *(offEnd - 1) << std::endl;
    std::cout << &*r << " : " << *r << std::endl;

}

输出:

0023FDAC :
0023FC9C : 13
0048C608 : 13

为什么迭代器的值相同但地址不同???!!!

这是否意味着&amp;*r == &amp;*(i-1) 不正确?

【问题讨论】:

  • std::cout &lt;&lt; &amp;(offEnd - 1) &lt;&lt; " : " &lt;&lt; *(offEnd - 1) &lt;&lt; std::endl; 是做什么的那你有答案了吗?
  • 您对链接文章的引用略有不同。在链接中,您会找到 &amp;*r == &amp;*(i-1),而不是您帖子中的内容。

标签: c++ reverse-iterator


【解决方案1】:

地址不同,因为你有不同的对象。 (offEnd - 1)r 是不同的对象。因为他们是,他们有不同的地址。您需要做的是取消引用迭代器,然后获取该地址。这样做会给你

int main()
{
    std::deque<int> di{ 1, 1, 2, 3, 5, 8, 13 }; // fibonacci series
    // deque has bi-directional iterators

    std::deque<int>::iterator offEnd = di.end(); // one-past the last element in di
    std::deque<int>::reverse_iterator r(offEnd); // constructing a reverse iterator from an iterator from deque<int> di

    std::cout << &(*offEnd) << " : " /*<< *r */ << std::endl;
    std::cout << &(*(offEnd - 1)) << " : " << *(offEnd - 1) << std::endl;
    std::cout << &*r << " : " << *r << std::endl;
}

哪个输出:

0xed3c8c : 
0xed3c88 : 13
0xed3c88 : 13

正如你所看到的,地址是相同的,因为迭代器指向同一个元素。


请注意

&(*offEnd)

是非法的并且是未定义的行为。 end() 处没有对象,因此取消对结束迭代器过去的引用是非法的。

【讨论】:

  • 代码在 MSVC++14 上崩溃。我认为这段代码中有一个 UB。因为在 GCC 上它可以工作。
  • @ItachiUchiwa 这可能是因为&amp;(*offEnd)。不允许取消引用结束迭代器。如果您删除std::cout &lt;&lt; &amp;(*offEnd) &lt;&lt; " : " /*&lt;&lt; *r */ &lt;&lt; std::endl;,它会崩溃吗?
  • 啊,没错!现在我已经删除了对offEnd 的取消引用,它工作正常!谢谢!
  • @ItachiUchiwa 酷。我已经在答案中添加了一个注释。
  • @Raindrop7 这仅适用于内置类型,然后它实际上是编译器错误。唯一的 UB 是 &amp;(*offEnd)
【解决方案2】:

原因很清楚,在查询offEndoffEnd-1的地址时也可以看到,它们是相同的。您正在查询迭代器的地址,如果您使用 --operator 在此迭代器中移动,则该地址保持不变。

【讨论】:

    猜你喜欢
    • 2012-12-13
    • 2010-10-27
    • 2018-09-23
    • 1970-01-01
    • 1970-01-01
    • 2018-02-16
    • 2018-07-14
    • 2017-08-29
    • 2016-07-24
    相关资源
    最近更新 更多