下面是remove的声明:
template<class ForwardIterator, class T>
ForwardIterator remove(ForwardIterator first, ForwardIterator last, const T& value);
remove需要一对迭代器来指定所要进行操作的元素区间,它不接受容器作为参数,所以remove并不知道这些元素被存放在哪个容器中。
从容器中删除元素的唯一方法是条用该容器的成员函数erase,而erase并不知道它元素所在的容器,所以remove不可能从容器中删除元素。这说明一个现象:用remove从容器中删除元素,而容器中的元素数目不会因此而减少:
vector<int> v;
v.reserve(10);
for (int i = 1; i <= 10; i++) {
v.push_back(i);
}
// 10
cout << v.size();
v[3] = v[5] = v[9] = 99;
remove(v.begin(), v.end(), 99);
// 仍然输出10
cout << v.size();
请记住:remove不是真正意义上的删除,因为它做不到。
下面看下remove究竟做了哪些工作:
remove移动了区间中的元素,结果是"不用被删除"的元素移动到了区间的前部(保持原来的顺序)。它返回的迭代器指向最后一个"不用被删除"的元素之后的元素。
举个例子,调用remove之前v的布局如下:
todo
一般情况下,在新的逻辑结尾后面的元素仍然保留其旧的值。调用了remove之后,v的布局如下:
todo
哪些你想要删除的元素很容易标识,它们位于原区间中,从newEnd到原区间的结尾。为了删除这些元素,只需调用区间形式的erase。
vector<int> v;
...
// 真正删除所有值为99的元素
v.erase(remove(v.begin(), v.end(), 99), v.end());
// 输出7
cout << v.size();
特例,remove和erase被合并起来融入到了list的remove成员函数中,这是STL中唯一一个名为remove并且确实删除了容器中元素的函数:
list<int> li;
...
// 删除所有值为99的元素,删除后li的大小会改变
li.remove(99);
注意:还有两个属于"remove类"的算法:remove_if和unique,同样适用于这种情形。
unique-erase:从容器中删除重复的值。
list::unique:从list中删除重复的值。