[5 算法] 32. 如果确实需要删除元素,需要在remove这一类算法之后调用erase

下面是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。

扫描二维码关注公众号,回复: 13439371 查看本文章
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中删除重复的值。

猜你喜欢

转载自blog.csdn.net/u012906122/article/details/119594124
今日推荐