【问题标题】:Erasing item in a for(-each) auto loop在 for(-each) 自动循环中擦除项目
【发布时间】:2014-10-23 09:11:32
【问题描述】:

在这样的 for 循环中使用自动变量时,有没有办法擦除特定元素?

for(auto a: m_Connections)
{
    if(something)
    {
        //Erase this element

    }
}

我知道我可以说

for(auto it=m_map.begin() ...

for(map<int,int>::iterator it=m_map.begin() ...

并手动增加迭代器(和擦除),但如果我能用更少的代码行来完成它,我会更开心。

谢谢!

【问题讨论】:

  • 擦除是什么意思?
  • m_Connections.erase(it);在“其他示例”中。

标签: c++ iterator std auto


【解决方案1】:

你不能。基于范围的循环使对范围的简单迭代更简单,但不支持使范围或它使用的迭代器无效的任何内容。当然,即使支持,如果不访问迭代器,您也无法有效地擦除元素。

你需要一个老式循环,类似于

for (auto it = container.begin(); it != container.end();) {
    if (something) {
        it = container.erase(it);
    } else {
        ++it;
    }
}

或者container.erase()std::remove_if 的组合,如果你喜欢那种东西的话。

【讨论】:

  • 个人风格:使用while(it != end(container)) {}
【解决方案2】:

不,没有。基于范围的 for 循环用于访问容器的每个元素一次。

每次从容器中删除元素时,被删除元素处或之后的迭代器都不再有效(给定the implementation of the range-based-for,这是一个问题)。

如果您需要随时修改容器,则应使用普通的 for 循环(或 while)。

如果要删除谓词返回true 的元素,一个好方法是:

m_Connections.erase(
  std::remove_if(m_Connections.begin(),
                 m_Connections.end(),
                 [](Type elem) { return predicate(elem); }),
  m_Connections.end());

std::remove_if 不会将迭代逻辑与谓词混合。

【讨论】:

    【解决方案3】:

    如果你想从容器中删除一个元素,你需要迭代器。
    而且您无法从元素本身获取迭代器——即使您可以,例如使用vector,内部使用的基于范围的迭代器将在下一步中失效,从而导致未定义的行为。

    所以答案是:不,在它的经典用法中你不能。基于范围的 for 专为方便地迭代范围内的所有元素而设计。

    【讨论】:

      【解决方案4】:

      将所有元素压入数组,然后进行弹出操作以删除该项目

      【讨论】:

      • 不会完全减少代码,而这正是 OP 的目标。
      猜你喜欢
      • 2013-10-08
      • 2015-11-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-07-08
      • 2016-09-07
      • 2012-05-30
      相关资源
      最近更新 更多