我正在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循环中实现的向后遍历方法?
答案 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++)
{
}