【问题标题】:Removal of elements during iteration through a list - safety在迭代期间通过列表删除元素 - 安全
【发布时间】:2010-01-27 19:00:48
【问题描述】:

我想知道这样的东西是否安全......

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

我知道以这种方式遍历向量会使迭代器无效,但同样的事情会发生在列表中吗?我认为不是因为列表是通过指针顺序排列的,而不是在内存中彼此“相邻”,但任何保证都会有所帮助。

【问题讨论】:

  • 注意:这对std::vector也是有效的,所有存在于vector中的迭代器都会失效,但是erase方法返回的迭代器是一个有效的迭代器。
  • 是的,但是安全我的意思是继续对容器进行操作会很好,因为其他迭代器不会失效(在这种情况下,除了一个被擦除的迭代器)。
  • 如果你有 other 迭代器,你最好确保它们不可能指向刚刚被删除的元素...

标签: c++ iteration


【解决方案1】:

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

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

    【解决方案3】:

    该标准为每个 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(),则增加两次(循环头第二次)。呸。

    【讨论】:

      【解决方案4】:

      是的,这是执行此操作的标准方法。请参阅有效 STL,第 9 条(第 46 页)。

      【讨论】:

        【解决方案5】:

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

        【讨论】:

          【解决方案6】:

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

          【讨论】:

          • 即使集合是一个列表,它也可能使 other 迭代器失效,前提是 other 迭代器指向被擦除的元素。
          【解决方案7】:

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

          【讨论】:

            猜你喜欢
            • 2013-01-29
            • 1970-01-01
            • 2018-07-18
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2016-11-21
            • 1970-01-01
            • 2011-07-04
            相关资源
            最近更新 更多