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

Ala*_*ley 34 c++ iterator stl traversal list

我正在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 ?
{
}
Run Code Online (Sandbox Code Playgroud)

这适用于Windows:

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

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

Fer*_*cio 60

使用reverse_iterator而不是迭代器.使用rbegin()和rend()代替begin()和end().

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

  • 区别在于你仍然使用"++ Iter"来增加迭代器,而不是"--Iter".或者我错了? (2认同)
  • 并非所有"前向"迭代器都是"双向的".这取决于集合类. (2认同)

mmo*_*cny 16

扭转最好/最简单的方法迭代一个列表(如前所述)使用反向迭代rbegin /雷德.

不过,我想提一提,反向迭代器实现存储"当前"迭代器位置的off-by-一个(GNU的执行标准库中至少).

这样做是为了简化实现,以使范围相反具有相同的语义的范围内向前[开始,结束)和[rbegin,分割)

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

  reference
  operator*() const
  {
_Iterator __tmp = current;
return *--__tmp;
  }
Run Code Online (Sandbox Code Playgroud)

因此,取消引用reverse_iterator比正常迭代器慢.

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

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

测试表明,对于循环体中使用的每个解引用,该解决方案要快〜5倍.

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

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


Ant*_*amp 13

你可能想要反向迭代器.从记忆里:

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

  • 谢谢,听起来不错。但当迭代器被认为是双向的时,创建一个特殊的反向迭代器似乎也是一种浪费 (2认同)

ejg*_*ttl 5

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

for (std::list<int>::reverse_iterator i = s.rbegin(); i != s.rend(); ++i)
Run Code Online (Sandbox Code Playgroud)


ste*_*enj 5

这应该工作:

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