24

如果我在循环中使用iteratorin并且在迭代器的当前迭代中使用,那么 for 循环应该继续正常并访问其余元素吗?foreraselist

根据我的阅读,这应该是这种情况,并且是listvs dequeor的主要区别特征vector。就我的目的而言,aqueue可能有效,但我需要这种行为。

这是我正在考虑的循环:

    std::list<Sequence>::iterator iterator;
    iterator=m_concurrents.begin();
    for (;iterator!=m_concurrents.end();++iterator){
        if (iterator->passes()){
            m_concurrents.erase(iterator);
        }
    }
4

3 回答 3

56

编写该循环的惯用方式是:

for (auto i = list.begin(); i != list.end();) {
    if (condition)
        i = list.erase(i);
    else
        ++i;
}

你可以用set, multiset, map, 或做同样的事情multimap。对于这些容器,您可以擦除元素而不影响任何迭代器对其他元素的有效性。其他容器喜欢vectordeque不那么好。对于那些容器,只有擦除迭代器之前的元素保持不变。这种差异仅仅是因为lists 将元素存储在单独分配的节点中。取出一个链接很容易。vectors 是连续的,取出一个元素会将其后的所有元素移回一个位置。

您的循环被破坏了,因为您i在某些给定条件下擦除了元素。i在该调用之后不再是有效的迭代器。然后您的for循环递增i,但i无效。人间地狱随之而来。这就是为什么erase在删除后将迭代器返回到元素的确切情况......所以你可以继续遍历list.

你也可以使用list::remove_if

list.remove_if([](auto& i) { return i > 10; });

在 lambda 中,如果应该删除元素,则返回 true。在此示例中,它将删除所有大于 10 的元素。

于 2013-04-29T00:50:17.103 回答
0
for (auto i = list.begin(); i != list.end(); ++i) {
    if (condition) {
        list.erase(i);
        --i;
    }
}
于 2017-09-22T08:34:58.117 回答
0

如果只想用for迭代器,可以这样使用,例如:

list<int> lst{4, 1, 2, 3, 5};

for(auto it = lst.begin(); it != lst.end();++it){
    if ((*it % 2) == 1){
        it = lst.erase(it);  erase and go to next(erase will return the next iterator)
        --it;  // as it will be add again in for, so we go back one step
    }
}

for(auto it:lst)cout<<it<<" ";
cout<<endl;  //4 2 

但是在迭代器中擦除while会更清楚:

list<int> lst{4, 1, 2, 3, 5};

auto it = lst.begin();
while (it != lst.end()){
    if((*it % 2) == 1){
        it = lst.erase(it);// erase and go to next
    } else{
        ++it;  // go to next
    }
}

for(auto it:lst)cout<<it<<" ";
cout<<endl;  //4 2

也可以使用成员函数remove_if:</p>

list<int> lst{4, 1, 2, 3, 5};

lst.remove_if([](int a){return a % 2 == 1;});

for(auto it:lst)cout<<it<<" ";
cout<<endl;  //4 2

或者使用std::remove_ifconbine with function erase

list<int> lst{4, 1, 2, 3, 5};

lst.erase(std::remove_if(lst.begin(), lst.end(), [](int a){
    return a % 2 == 1;
}), lst.end());

for(auto it:lst)cout<<it<<" ";
cout<<endl;  //4 2

您还可以参考这个问题: Removing item from vector, while in C++11 range 'for' loop?

于 2018-10-24T01:16:54.760 回答