std::list的循环迭代

Circular iteration of std::list

本文关键字:迭代 循环 list std      更新时间:2023-10-16

在我的应用程序中,我需要能够遍历一个双链接列表,从列表的任何任意成员开始,一直遍历到end(),然后一直遍历到begin(),直到遍历到达开始位置。

我决定使用std::list作为底层数据结构,并编写了一个circulate例程来实现这一点。然而,当它从end()循环到begin()时,它会显示出某些意想不到的行为。这是我的实现

template <class Container, class BiDirIterator>
void circulate(Container container, BiDirIterator cursor,
  std::function<void(BiDirIterator current)> processor)
{
  BiDirIterator start = cursor;
  do {
    processor(cursor);
    cursor++;
    if (cursor == container.end()) {
      cursor = container.begin(); // [A]
    }
  } while (cursor != start);
}
// ...
typedef int T;
typedef std::list<T> TList;
typedef TList::iterator TIter;
int count = 0;
TList l;
l.push_back(42);
circulate<TList, TIter>(
  l, l.begin(),
  [&](TIter cur) {
    std::cout << *cur << std::endl;
    count++;
  }
);

输出为:

42
-842150451

当我遍历代码时,我发现标记为[A]的行永远不会到达。光标永远不等于container.end()。令人惊讶的是,在该游标上调用++,会在下一次传递中自动将其带到container.begin()。(我想这是STL实现特有的)。

如何修复此行为?

这里的问题是按值获取Container。这会导致复制,因此container.end()container.begin()返回的迭代器与传递给函数的迭代程序不同。相反,如果通过引用传递Container,则代码工作正常。

实例