【问题标题】:how to erase from vector in range-based loop?如何在基于范围的循环中从向量中擦除?
【发布时间】:2015-09-28 13:18:06
【问题描述】:

我只是想擦除基于范围的循环中的指定元素:

vector<int> vec = { 3, 4, 5, 6, 7, 8 };
for (auto & i:vec)
{
    if (i>5)
    vec.erase(&i);
}

怎么了?

【问题讨论】:

标签: c++11 vector


【解决方案1】:

您不能在 std::vector 上按值擦除元素,并且由于基于范围的循环直接公开值,因此您的代码没有意义 (vec.erase(&amp;i))。

主要问题是std::vector 在删除元素时会使其迭代器无效。

所以既然基于范围的循环基本上是这样实现的

auto begin = vec.begin();
auto end = vec.end()
for (auto it = begin; it != end; ++it) {
  ..
}

然后删除一个值会使it 失效并中断连续的迭代。

如果你真的想在迭代时删除一个元素,你必须注意正确更新迭代器:

for (auto it = vec.begin(); it != vec.end(); /* NOTHING */)
{
  if ((*it) > 5)
    it = vec.erase(it);
  else
    ++it;
}  

【讨论】:

    【解决方案2】:

    从您正在迭代的向量中删除元素通常是一个坏主意。在您的情况下,您很可能会跳过 7。更好的方法是使用 std::remove_if

    vec.erase(std::remove_if(vec.begin(), vec.end(),
                              [](const int& i){ return i > 5; }),
               vec.end());
    

    std::remove 将应该删除的元素移到容器的末尾,并将迭代器返回到这些元素中的第一个。你只需要删除这些元素直到最后。

    【讨论】:

    【解决方案3】:

    这很简单:不要使用基于范围的循环。这些循环旨在作为一种简洁的形式依次迭代容器中的所有如果您想要更复杂的东西(例如擦除或通常访问迭代器),以明确的方式进行:

    for (auto it = begin(vec); it != end(vec);) {
      if (*it > 5)
        it = vec.erase(it);
      else
        ++it;
    }
    

    【讨论】:

    • vec 超出范围!
    • @ifooi Er,什么?你能详细说明一下吗?
    • for (const auto &i : vec) std::cout
    • 对不起;我不正确,把我的代码弄乱了
    猜你喜欢
    • 2020-07-17
    • 1970-01-01
    • 1970-01-01
    • 2014-05-16
    • 2020-05-03
    • 1970-01-01
    • 2015-04-26
    • 2018-07-21
    • 1970-01-01
    相关资源
    最近更新 更多