你如何在STL列表中向后迭代?

时间:2008-10-09 19:57:10

标签: c++ list stl iterator traversal

我正在Windows和Mac之间编写一些跨平台代码。

如果list :: end()“返回一个迭代器来解决列表中最后一个元素之后的位置”并且可以在向前遍历列表时进行检查,那么向后遍历的最佳方法是什么?

此代码适用于Mac但不适用于Windows(不能超出第一个元素):

list<DVFGfxObj*>::iterator iter = m_Objs.end();
for (iter--; iter!=m_Objs.end(); iter--)// By accident discovered that the iterator is circular ?
{
}

这适用于Windows:

list<DVFGfxObj*>::iterator iter = m_Objs.end();
    do{
        iter--;
    } while (*iter != *m_Objs.begin());

是否有另一种可以在for循环中实现的向后遍历方法?

5 个答案:

答案 0 :(得分:60)

使用reverse_iterator而不是迭代器。 使用rbegin()&amp; rend()而不是begin()&amp;端()。

如果您喜欢使用BOOST_FOREACH宏,另一种可能性是使用Boost 1.36.0中引入的BOOST_REVERSE_FOREACH宏。

答案 1 :(得分:16)

反向迭代列表的最佳/最简单方法是(如前所述)使用反向迭代器rbegin / rend。

但是,我确实想提一下,反向迭代器实现了一个一个地存储“当前”迭代器位置(至少在标准库的GNU实现上)。

这样做是为了简化实现,以使反向范围具有与前向范围[begin,end]和[rbegin,rend)相同的语义

这意味着解除引用迭代器涉及创建一个新的临时,然后递减它,每次

  reference
  operator*() const
  {
_Iterator __tmp = current;
return *--__tmp;
  }

因此,解除引用reverse_iterator比正常迭代器慢。

但是,您可以使用常规双向迭代器自己模拟反向迭代,避免这种开销:

for ( iterator current = end() ; current != begin() ; /* Do nothing */ )
{
    --current; // Unfortunately, you now need this here
    /* Do work */
    cout << *current << endl;
}

测试表明,对于循环体中使用的每个解除引用,此解决方案的速度要快〜5倍。

注意:上面的代码没有进行测试,因为std :: cout会成为瓶颈。

另请注意:'挂钟时间'差异为~5秒,std :: list大小为1000万个元素。实际上,除非您的数据大小那么大,只需坚持使用rbegin()rend()!

答案 2 :(得分:13)

您可能想要反向迭代器。来自记忆:

list<DVFGfxObj*>::reverse_iterator iter = m_Objs.rbegin();
for( ; iter != m_Objs.rend(); ++iter)
{
}

答案 3 :(得分:5)

正如Ferruccio已经提到的,使用reverse_iterator:

for (std::list<int>::reverse_iterator i = s.rbegin(); i != s.rend(); ++i)

答案 4 :(得分:5)

这应该有效:

list<DVFGfxObj*>::reverse_iterator iter = m_Objs.rbegin();
for (; iter!= m_Objs.rend(); iter++)
{
}