如何在循环时从矢量中删除元素?

zeb*_*bra 16 c++

我正在循环一个带有循环的向量,例如for(int i = 0; i < vec.size(); i++).在这个循环中,我检查该向量索引处元素的条件,如果某个条件为真,我想删除该元素.

如何在循环时删除矢量元素而不会崩溃?

Fre*_*abe 31

从STL容器中删除满足给定谓词的所有元素的惯用方法是使用删除擦除习惯用法.我们的想法是将谓词(即为某个元素产生真或假的函数)移动到给定函数中,比如说pred:

static bool pred( const std::string &s ) {
  // ...
}

std::vector<std::string> v;
v.erase( std::remove_if( v.begin(), v.end(), pred ), v.end() );
Run Code Online (Sandbox Code Playgroud)

如果您坚持使用索引,则不应该为每个元素增加索引,而只是针对那些未被删除的元素:

std::vector<std::string>::size_type i = 0;
while ( i < v.size() ) {
    if ( shouldBeRemoved( v[i] ) ) {
        v.erase( v.begin() + i );
    } else {
        ++i;
    }
}
Run Code Online (Sandbox Code Playgroud)

然而,这不仅仅是更多的代码和更少的惯用(读取:C++程序员实际上必须查看代码,而'擦除和删除'成语立即给出一些想法正在发生),但也因为向量存储他们的元素效率低得多在一个连续的存储器块中,因此擦除除矢量端以外的位置也会在段擦除后将所有元素移动到新的位置.


Ker*_* SB 9

如果你不能使用remove/erase(例如因为你不想使用lambdas或写一个谓词),请使用标准习语来删除序列容器元素:

for (auto it = v.cbegin(); it != v.cend() /* not hoisted */; /* no increment */)
{
    if (delete_condition)
    {
        it = v.erase(it);
    }
    else
    {
        ++it;
    }
}
Run Code Online (Sandbox Code Playgroud)

如果可能的话,更喜欢删除/删除:

#include <algorithm>

v.erase(std::remove_if(v.begin(), v.end(),
                       [](T const & x) -> bool { /* decide */ }),
        v.end());
Run Code Online (Sandbox Code Playgroud)


Fre*_*son 8

使用Erase-Remove Idiom,使用remove_if谓词指定您的条件.