迭代STL容器并删除/添加多个项目

Gra*_*pes 2 c++ c++11

我的代码中出现的最常见错误之一是在循环期间修改STL容器.

在循环执行期间删除或添加元素,因此我经常遇到超出范围的异常.

我的for循环通常看起来像这样:

for (auto& Item : Items) { // Will not work when Items container is modified
    //... loop logic
}
Run Code Online (Sandbox Code Playgroud)

当可以删除多个项目时,我使用这个怪物:

for (int Index=Items.size()-1;Index<=0;Index--) {
    if (Index<Items.size()) { //Because multiple items can be removed in a single loop
        //... loop logic
    }
}
Run Code Online (Sandbox Code Playgroud)

这看起来很糟糕,这让我觉得使用第二个选项感觉很糟糕.可以删除多个项目的原因是由于事件,单个事件可以删除任意数量的元素.

下面是一些伪代码来说明何时发生这种情况:

// for each button in vector<button> {
// process button events
// event adds more buttons to vector<button>
// *ERROR* vector<button> is modified during loop.
// }
Run Code Online (Sandbox Code Playgroud)

在另一个示例中,想象一个包含以下项的向量:

// 0 1 2 3 4 5 6 7 8 9
Run Code Online (Sandbox Code Playgroud)

我们开始循环,0逐个元素地去.在4,我想删除的元素1,4并且9因此我们不能在这里使用一个正常的循环.

rec*_*que 7

std::remove_if与谓词一起使用,该谓词决定是否需要删除按钮:

bool needsRemoved(const Button& button);

vec.erase(std::remove_if(vec.begin(), vec.end(), &needsRemoved), vec.end());
Run Code Online (Sandbox Code Playgroud)

编辑:对于您的上一个示例,二次(即性能不佳)算法是:

std::vector<int> vec = {0,1,2,3,4,5,6,7,8,9};
auto end = vec.end();
for (auto it = vec.begin(); it < end; ++it)
{
    std::set<int> bad = {1, 4, 9};
    end = std::remove_if
        (vec.begin(), end,
         [bad](int x) { return (bad.find(x) != bad.end()); });
}
vec.erase(end, vec.end());
Run Code Online (Sandbox Code Playgroud)

您可能最好使用快速查找的容器(如集合或地图).

  • 这是如何解决他的问题的.他的问题是按钮4中的某些内容可能会删除按钮1,4和9.在循环中使迭代器无效. (2认同)