提问人:AlanKley 提问时间:10/10/2008 最后编辑:Abderrahmene Rayene MihoubAlanKley 更新时间:11/17/2023 访问量:60182
如何向后遍历 STL 列表?
How do you iterate backwards through an STL 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 ?
{}
这适用于 Windows:
list<DVFGfxObj*>::iterator iter = m_Objs.end();
do{
iter--;
} while (*iter != *m_Objs.begin());
有没有另一种可以在 for 循环中实现的向后遍历方法?
答:
使用 代替 。
使用 & 而不是 & 。reverse_iterator
iterator
rbegin()
rend()
begin()
end()
如果您喜欢使用 BOOST_FOREACH
宏,另一种可能性是使用 Boost 1.36.0 中引入的宏。BOOST_REVERSE_FOREACH
评论
您可能需要反向迭代器。从记忆中:
list<DVFGfxObj*>::reverse_iterator iter = m_Objs.rbegin();
for( ; iter != m_Objs.rend(); ++iter)
{
}
评论
for (auto iter=m_Objs.rbegin(); iter != m_Objs.rend(); ++iter)
正如 Ferruccio 已经提到的,使用reverse_iterator:
for (std::list<int>::reverse_iterator i = s.rbegin(); i != s.rend(); ++i)
评论
for (auto iter=m_Objs.rbegin(); iter != m_Objs.rend(); ++iter)
这应该有效:
list<DVFGfxObj*>::reverse_iterator iter = m_Objs.rbegin();
for (; iter!= m_Objs.rend(); iter++)
{
}
评论
for (auto iter=m_Objs.rbegin(); iter != m_Objs.rend(); ++iter)
反向迭代列表的最佳/最简单的方法是(如前所述)使用反向迭代器 rbegin/rend。
然而,我确实想提一下,反向迭代器是将“当前”迭代器位置存储的(至少在标准库的 GNU 实现中)。
这样做是为了简化实现,以便反向范围与范围 forward [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()!
评论
current == begin()
)
评论