且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

如何从一个向量中删除一个元素,当它循环?

更新时间:2023-11-10 08:09:16

从STL容器中删除所有元素的惯用方法,谓词是使用删除删除成语。这个想法是将谓词(即对某些元素产生真或假的函数)移动到给定的函数中,例如 pred ,然后:

The idiomatic way to remove all elements from an STL container which satisfy a given predicate is to use the remove-erase idiom. The idea is to move the predicate (that's the function which yields true or false for some element) into a given function, say pred and then:

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

std::vector<std::string> v;
v.erase( std::remove_if( v.begin(), v.end(), pred ), v.end() );

如果你坚持使用索引,你不应该增加每个元素的索引,它没有被删除:

If you insist on using indices, you should not increment the index for every element, but only for those which didn't get removed:

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

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

However, this is not only more code and less idiomatic (read: C++ programmers actually have to look at the code whereas the 'erase & remove' idiom immediately gives some idea what's going on), but also much less efficient because vectors store their elements in one contiguous block of memory, so erasing on positions other than the vector end also moves all the elements after the segment erased to their new positions.