如何向后迭代 STL 列表?
我正在编写一些 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 循环中实现的向后遍历方法?
I'm writing some cross-platform code between Windows and 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 the list backwards?
This code works on the Mac but not on Windows (can't decrement beyond first element):
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:
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?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
使用
reverse_iterator
而不是iterator
。使用 rbegin() 和
rend()
而不是begin()
&结束()
。另一种可能性,如果您喜欢使用
BOOST_FOREACH
宏是使用 Boost 1.36.0 中引入的
BOOST_REVERSE_FOREACH
宏。Use
reverse_iterator
instead ofiterator
.Use
rbegin()
&rend()
instead ofbegin()
&end()
.Another possibility, if you like using the
BOOST_FOREACH
macro is to use theBOOST_REVERSE_FOREACH
macro introduced in Boost 1.36.0.反向迭代列表的最佳/最简单方法是(如前所述)使用反向迭代器 rbegin/rend。
然而,我确实想提一下,反向迭代器的实现是逐一存储“当前”迭代器位置(至少在标准库的 GNU 实现上)。
这样做是为了简化实现,以便反向范围具有与正向范围 [begin, end) 和 [rbegin, rend) 相同的语义。
这意味着取消引用迭代器涉及创建一个新的临时值,并且然后递减它,每次:
因此,取消引用反向迭代器比普通迭代器慢。
但是,您可以使用常规双向迭代器自己模拟反向迭代,避免这种开销:
测试表明,对于循环体中使用的每次取消引用,此解决方案的速度大约快 5 倍。
注意:上面的代码没有进行测试,因为 std::cout 可能是瓶颈。
另请注意:当 std::list 大小为 1000 万个元素时,“挂钟时间”差异约为 5 秒。 所以,实际上,除非你的数据量很大,否则就坚持使用 rbegin() rend()!
The best/easiest way to reverse iterate a list is (as already stated) to use reverse iterators 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).
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)
What this means is that dereferencing an iterator involves creating a new temporary, and then decrementing it, each and every time:
Thus, dereferencing a reverse_iterator is slower than an normal iterator.
However, You can instead use the regular bidirectional iterators to simulate reverse iteration yourself, avoiding this overhead:
Testing showed this solution to be ~5 times faster for each dereference used in the body of the loop.
Note: Testing was not done with the code above, as that std::cout would have been the bottleneck.
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()!
您可能需要反向迭代器。 从记忆里:
You probably want the reverse iterators. From memory:
正如Ferruccio 已经提到的,使用reverse_iterator:
As already mentioned by Ferruccio, use reverse_iterator:
这应该有效:
This should work: