如何从基于范围的循环中的矢量中删除?

Mos*_*hri 10 vector c++11

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

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

怎么了?

Jac*_*ack 18

你不能通过a上的值擦除元素std::vector,并且由于基于范围的循环直接暴露了你的代码没有意义的值(vec.erase(&i)).

主要问题是std::vector当擦除元素时,它的迭代器无效.

因此,基于范围的循环基本上实现为

auto begin = vec.begin();
auto end = vec.end()
for (auto it = begin; it != end; ++it) {
  ..
}
Run Code Online (Sandbox Code Playgroud)

然后擦除一个值将使无效it并中断连续的迭代.

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

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


use*_*027 12

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

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

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

  • 我们现在有[`std :: experimental :: erase_if`](http://en.cppreference.com/w/cpp/experimental/vector/erase_if). (4认同)

Rei*_*ica 5

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

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