迭代期间通过列表删除元素 - 安全性

时间:2010-01-27 19:00:48

标签: c++ iteration

我想知道这样的事情是否安全......

// Iterating through a <list>
while ( iter != seq.end()) {
  if ( test ) {
    iter = seq.erase( iter );
  } else {
    ++iter;
 }

我知道以这种方式迭代向量会使迭代器失效,但是列表中会出现同样的情况吗?我假设没有,因为列表是通过指针顺序而不是在内存中相互“下一步”,但任何保证都会有所帮助。

7 个答案:

答案 0 :(得分:5)

这很好,因为erase方法返回一个新的有效迭代器。

答案 1 :(得分:1)

是的,这是执行此操作的标准方法。见有效STL,第9项(第46页)。

答案 2 :(得分:1)

是 - std::list::erase():“仅使迭代器和对已擦除元素的引用无效。”

那就是说,你可能根本不应该这样做 - 你似乎试图模仿std::remove_if()

答案 3 :(得分:1)

标准为每个STL容器定义erase行为。对于std::list,仅擦除元素的迭代器无效。但erase的返回值不一定是不可分辨的(可能是list.end())。

因此,要清除列表中的所有元素,以下内容绝对有效:

.. it = l.begin();
while(it != l.end()) {
   it = l.erase(it);
}

但要注意这样的事情(危险的陷阱):

for (.. it  = l.begin; it != l.end(); ++it) {
      it = l.erase(it);
   }

如果是l.end(),则增加两次(循环头第二次)。 Baamm。

答案 4 :(得分:0)

是的,这是完全安全的。 erase()函数返回一个迭代器,该迭代器是在被擦除的元素之后的元素。如果你没有将erase()的结果重新分配给iter,你就会遇到麻烦。

答案 5 :(得分:0)

正如其他人所解释的那样,您的代码不会使函数中使用的迭代器无效。但是,如果集合是向量, 会使其他迭代器无效,但如果集合是列表则不会。

答案 6 :(得分:0)

正如其他人所说,是的,它会起作用。但我建议改用list::remove_if,因为它更具表现力。