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

时间:2015-07-09 23:04:01

标签: c++11 vector

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

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

出了什么问题?

3 个答案:

答案 0 :(得分:15)

您无法按std::vector上的值删除元素,并且由于基于范围的循环直接暴露了您的代码没有意义的值(vec.erase(&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;
}  

答案 1 :(得分:11)

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

mySubscribers

vec.erase(std::remove_if(vec.begin(), vec.end(), [](const int& i){ return i > 5; }), vec.end()); 将应删除的元素移到容器的末尾,并将迭代器返回到第一个元素。你只需要删除那些元素直到最后。

答案 2 :(得分:4)

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

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