我想知道在 C++ 中从向量中删除元素的最佳实践是什么。
我见过很多次人们使用 std::remove 来查找并删除元素,然后使用擦除从向量中删除元素。
但是为什么它比使用 find 获取要删除的元素的迭代器然后使用该迭代器进行擦除更好呢?
谢谢
std::find
后跟 vector::erase
将从 vector
中删除第一次出现的具有给定值的对象。
std::vector<int> vec{1,3,3,8,3,5};
vec.erase(std::find(vec.begin(), vec.end(), 3));
//vec == {1,3,8,3,5}
std::remove
后跟 vector::erase
将从 vector
中删除每一个具有给定值的对象。
std::vector<int> vec{1,3,3,8,3,5};
vec.erase(std::remove(vec.begin(), vec.end(), 3), vec.end());
//vec == {1,8,5}
没有更好,他们只是做不同的事情。
std::remove
更普遍有用,这就是为什么它更常见;特别是,当向量中不存在元素时,std::remove
后跟vector::erase
不执行任何操作,而std::find
后跟vector::erase
具有未定义的行为。
请注意,“查找-擦除”、“删除-擦除”都保持元素的相对顺序。如果你想从向量中删除一个元素,但不关心元素的结果顺序,你可以使用“find-move-pop_back”或“partition-erase”:
//find-move-pop_back
std::vector<int> vec{1,3,3,8,3,5};
*std::find(vec.begin(), vec.end(), 3) = std::move(vec.back());
vec.pop_back();
//partition-erase
std::vector<int> vec{1,3,3,8,3,5};
vec.erase(
std::partition(vec.begin(), vec.end(), [](int v){return v != 3;}),
vec.end());
你是对的,
std::erase
和std::remove
只是返回一个迭代器。但 std::remove
做了一件事不同:它首先将要删除的元素移动到向量的末尾。然后你打算从元素 std::erase
调用 std::remove
返回,到向量的末尾。
您可以使用该属性来找出从 std::vector 中删除了多少元素:
void print( vector<string> &v ) {
for( auto&& s : v ) {
printf( " - %s\n", s.c_str() );
}
puts("");
}
int main() {
vector<string> s = { "Strings", "a", "in", "a", "a", "a", "test", "test", "a", "a", "vector" } ;
puts( "Original" );
print( s );
auto it = std::remove( s.begin(), s.end(), "a" );
printf( "Deleting %d elts\n", s.end() - it );
s.erase( it, s.end() );
puts( "After" );
print( s );
}