首先,我们使用整数来填充一个std::vector实例,之后剔除一些特定元素。我们演示的从vector实例中删除元素正确的方法。
#include
#include
#include
using namespace std;
vector实例,并用整数填满它。int main(){
vector v{1, 2, 3, 2, 5, 2, 6, 2, 4, 8};
const auto new_end(remove(begin(v), end(v), 2));
vector在删除这些元素之后,长度并没有发生变化。那么下一步就让这个vector变得短一些。 v.erase(new_end, end(v));
vector实例中所包含的元素。 for(auto i : v){
cout << i << ", ";
}
cout << '\n';
const auto odd([](int i){return i % 2 != 0;});
remove_if函数,使用上面定义的谓词函数,来删除特定的元素。这里我们将上面删除元素的步骤合二为一。 v.erase(remove_if(begin(v), end(v), odd), end(v));
vector实例的容量依旧是10。最后一步中,我们将其容量修改为正确的大小。需要注意的是,这个操作会让vector重新分配一段内存,以匹配相应元素长度,vector中已存的元素会移动到新的内存块中。 v.shrink_to_fit();
vector实例中的元素。 for (auto i : v) {
cout << i << ", ";
}
cout << '\n';
}
vector实例中所存在的元素。$ ./main
1, 3, 5, 6, 4, 8,
6, 4, 8,
从vector中移除2的代码如下所示:
const auto new_end (remove(begin(v), end(v), 2));
v.erase(new_end, end(v));
std::begin和std::end函数都以一个vector实例作为参数,并且返回其迭代器,迭代器分别指向第一个元素和最后一个元素,就如下图所示。

每次移除一个元素, new_end向前移动一下

std::remove只是将要删除的元素移动到容器末尾,而不是将其真正删除,所以这个函数也可以用于不支持空间大小变化的数据类型。
std::remove在删除2的时候,会先将非2元素进行移动,然后修改end迭代器的指向。该算法将严格保留所有非2个值的顺序。
注解
调用 std::remove 常后随容器的 erase 成员函数,它擦除未指定值并减小容器的物理大小以匹配其新的逻辑大小。这两个调用一并被称为擦除-移除手法,它可通过对所有标准序列容器重载的 std::erase 自由函数,或对所有标准容器重载的 std::erase_if 自由函数达成 (C++20 起)。
同名的容器成员函数 list::remove、 list::remove_if、 forward_list::remove 及 forward_list::remove_if 擦除被移除的元素。
这些算法通常不能用于如 std::set 与 std::map 的关联容器,因为其迭代器类型不解引用为可移动赋值 (MoveAssignable) 类型(这些容器中的键不可修改)。
标准库亦于 定义 std::remove 的重载,它接收 const char* 的重载并用于删除文件。
因为 std::remove 以引用接收 value ,若引用到范围 [first, last) 中的元素,则它可能有不可预期的行为。
在2步中,2的值仍然存在,并且vector应该变短。并且4和8在现有的vector中重复了。这是怎么回事?
让我们再来看一下所有的元素,目前vector的范围并不是原来那样了,其是从begin迭代器,到new_end迭代器。new_end之后的值其实就不属于vector实例了。我们会注意到,在这个范围内的数值,就是我们想要的正确结果,也就是所有的2都被移除了。
最后,也就是为什么要调用erase函数:我们需要告诉vector实例,new_end到end之间的元素我们不需要了。我们仅需要保留begin到new_end间的元素就好了。erase函数会将end指向new_end。这里需要注意的是std::remove会直接返回new_end迭代器,所以我们可以直接使用它。
Note:
vector在这里不仅仅移动了内部指针。如果vector中元素比较复杂,那么在移除的时候,会使用其析构函数来销毁相应的对象。
最后,这个向量就如步骤3所示:的确变短了。那些旧的元素已经不在vector的访问范围内了,不过其仍存储在内存中。
为了不让vector浪费太多的内存,我们在最后调用了shrink_to_fit。该函数会为元素分配足够的空间,将剩余的元素移到该空间内,并且删除之前那个比较大的内存空间。
在上面的第8步中,我们定义了一个谓词函数,并在std::remove_if中使用了它。因为不论删除函数返回怎么样的迭代器,在对vector实例使用擦除函数都是安全的。如果vector中全是偶数,那么std::remove_if不会做任何事情,并且返回end迭代器。之后的调用就为v.erase(end, end); ,同样没有做任何事情。

#include
#include
#include
using namespace std;
int main()
{
vector<int> v {1, 2, 3, 2, 5, 2, 6, 2, 4, 8};
{
const auto new_end (remove(begin(v), end(v), 2));
for (auto i : v) {
cout << i << ", ";
}
cout << '\n';
v.erase(new_end, end(v));
}
for (auto i : v) {
cout << i << ", ";
}
cout << '\n';
{
const auto odd ([](int i) { return i % 2 != 0; });
const auto new_end (remove_if(begin(v), end(v), odd));
v.erase(new_end, end(v));
}
v.shrink_to_fit();
for (auto i : v) {
cout << i << ", ";
}
cout << '\n';
}
输出
