如何向后迭代 STL 列表?

发布于 2024-07-07 18:24:55 字数 631 浏览 4 评论 0原文

我正在编写一些 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

伏妖词 2024-07-14 18:24:55

使用 reverse_iterator 而不是 iterator
使用 rbegin() 和 rend() 而不是 begin() & 结束()

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

Use reverse_iterator instead of iterator.
Use rbegin() & rend() instead of begin() & end().

Another possibility, if you like using the BOOST_FOREACH macro is to use the BOOST_REVERSE_FOREACH macro introduced in Boost 1.36.0.

杯别 2024-07-14 18:24:55

反向迭代列表的最佳/最简单方法是(如前所述)使用反向迭代器 rbegin/rend。

然而,我确实想提一下,反向迭代器的实现是逐一存储“当前”迭代器位置(至少在标准库的 GNU 实现上)。

这样做是为了简化实现,以便反向范围具有与正向范围 [begin, end) 和 [rbegin, rend) 相同的语义。

这意味着取消引用迭代器涉及创建一个新的临时值,并且然后递减它,每次

  reference
  operator*() const
  {
_Iterator __tmp = current;
return *--__tmp;
  }

因此,取消引用反向迭代器比普通迭代器慢。

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

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

测试表明,对于循环体中使用的每次取消引用,此解决方案的速度大约快 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:

  reference
  operator*() const
  {
_Iterator __tmp = current;
return *--__tmp;
  }

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:

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 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()!

找个人就嫁了吧 2024-07-14 18:24:55

您可能需要反向迭代器。 从记忆里:

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

You probably want the reverse iterators. From memory:

list<DVFGfxObj*>::reverse_iterator iter = m_Objs.rbegin();
for( ; iter != m_Objs.rend(); ++iter)
{
}
帝王念 2024-07-14 18:24:55

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

for (std::list<int>::reverse_iterator i = s.rbegin(); i != s.rend(); ++i)

As already mentioned by Ferruccio, use reverse_iterator:

for (std::list<int>::reverse_iterator i = s.rbegin(); i != s.rend(); ++i)
一笔一画续写前缘 2024-07-14 18:24:55

这应该有效:

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

This should work:

list<DVFGfxObj*>::reverse_iterator iter = m_Objs.rbegin();
for (; iter!= m_Objs.rend(); iter++)
{
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文