C++ 你如何通过 STL 列表向后迭代?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/188942/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do you iterate backwards through an STL list?
提问by AlanKley
I'm writing some cross-platform code between Windows and Mac.
我正在编写一些 Windows 和 Mac 之间的跨平台代码。
If list::end() "returns an iterator that addresses the location succeeding the last element in a list" and can be checked when traversing a list forward, what is the best way to traverse backwards?
如果 list::end() “返回一个迭代器,该迭代器寻址列表中最后一个元素之后的位置”并且可以在向前遍历列表时进行检查,那么向后遍历的最佳方法是什么?
This code workson the Mac but not on Windows (can't decrement beyond first element):
此代码适用于 Mac,但不适用于 Windows(不能递减超过第一个元素):
list<DVFGfxObj*>::iterator iter = m_Objs.end();
for (iter--; iter!=m_Objs.end(); iter--)// By accident discovered that the iterator is circular ?
{
}
this works on Windows:
这适用于 Windows:
list<DVFGfxObj*>::iterator iter = m_Objs.end();
do{
iter--;
} while (*iter != *m_Objs.begin());
Is there another way to traverse backward that could be implemented in a for loop?
是否有另一种可以在 for 循环中实现的向后遍历方法?
回答by Ferruccio
Use reverse_iterator instead of iterator. Use rbegin() & rend() instead of begin() & end().
使用 reverse_iterator 而不是迭代器。使用 rbegin() & rend() 而不是 begin() & end()。
Another possibility, if you like using the BOOST_FOREACHmacro is to use the BOOST_REVERSE_FOREACH macro introduced in Boost 1.36.0.
另一种可能性,如果您喜欢使用BOOST_FOREACH宏,则使用 Boost 1.36.0 中引入的 BOOST_REVERSE_FOREACH 宏。
回答by mmocny
The best/easiest way to reverse iterate a list is (as already stated) to use reverse iterators rbegin/rend.
反向迭代列表的最佳/最简单的方法是(如前所述)使用反向迭代器 rbegin/rend。
However, I did want to mention that reverse iterators are implemented storing the "current" iterator position off-by-one (at least on the GNU implementation of the standard library).
但是,我确实想提一下,反向迭代器的实现是逐一存储“当前”迭代器位置(至少在标准库的 GNU 实现上)。
This is done to simplify the implementation, in order for the range in reverse to have the same semantics as a range forward [begin, end) and [rbegin, rend)
这样做是为了简化实现,以便反向范围与正向范围 [begin, end) 和 [rbegin, rend) 具有相同的语义
What this means is that dereferencing an iterator involves creating a new temporary, and then decrementing it, each and every time:
这意味着取消引用迭代器涉及创建一个新的临时对象,然后每次都递减它:
reference
operator*() const
{
_Iterator __tmp = current;
return *--__tmp;
}
Thus, dereferencing a reverse_iterator is slower than an normal iterator.
因此,取消引用 reverse_iterator 比普通迭代器慢。
However, You can instead use the regular bidirectional iterators to simulate reverse iteration yourself, avoiding this overhead:
但是,您可以改为使用常规的双向迭代器来自己模拟反向迭代,从而避免这种开销:
for ( iterator current = end() ; current != begin() ; /* Do nothing */ )
{
--current; // Unfortunately, you now need this here
/* Do work */
cout << *current << endl;
}
Testing showed this solution to be ~5 times faster for each dereferenceused in the body of the loop.
测试表明,对于循环体中使用的每个取消引用,此解决方案的速度提高了约 5 倍。
Note: Testing was not done with the code above, as that std::cout would have been the bottleneck.
注意:上面的代码没有完成测试,因为 std::cout 会成为瓶颈。
Also Note: the 'wall clock time' difference was ~5 seconds with a std::list size of 10 million elements. So, realistically, unless the size of your data is that large, just stick to rbegin() rend()!
另请注意:“挂钟时间”差异约为 5 秒,std::list 大小为 1000 万个元素。因此,实际上,除非您的数据大小如此之大,否则只需坚持使用 rbegin() rend()!
回答by Anthony Cramp
You probably want the reverse iterators. From memory:
您可能想要反向迭代器。从记忆里:
list<DVFGfxObj*>::reverse_iterator iter = m_Objs.rbegin();
for( ; iter != m_Objs.rend(); ++iter)
{
}
回答by ejgottl
As already mentioned by Ferruccio, use reverse_iterator:
正如 Ferruccio 已经提到的,使用 reverse_iterator:
for (std::list<int>::reverse_iterator i = s.rbegin(); i != s.rend(); ++i)
回答by steffenj
This should work:
这应该有效:
list<DVFGfxObj*>::reverse_iterator iter = m_Objs.rbegin();
for (; iter!= m_Objs.rend(); iter++)
{
}