移除(removing)元素
算法remove()自某个区间删除元素,然而如果使用它来删除容器的所有元素,其行为可能不能达到预期。
例如:
#include<iostream>
#include<list>
#include<algorithm>
#include<iterator>
using namespace std;
int main() {
list<int> coll;
for (int i = 1; i <= 6; ++i) {
coll.push_back(i);
coll.push_front(i);
}
cout << "pre: ";
copy(coll.begin(), coll.end(), ostream_iterator<int>(cout, " "));
cout << endl;
remove(coll.begin(), coll.end(), 3);
cout << "post: ";
copy(coll.begin(), coll.end(), ostream_iterator<int>(cout, " "));
cout << endl;
return 0;
}
可能大部分人会认为,这个程序必然会删除数值为3的所有元素,但程序输出结果如下:
pre: 6 5 4 3 2 1 1 2 3 4 5 6
post: 6 5 4 2 1 1 2 4 5 6 5 6
remove()并没有改变群集中元素的数量。end()返回的还是当初的那个终点,size()返回的还是当初的那个大小。不过元素的次序变了,数值为3的元素被之后的元素所覆盖(如图5.7),至于群集尾端的那些未被覆盖的元素,原封不动-------逻辑上来说,那些元素已经不属于这个群集了。
事实上这个算法返回一个新的终点。可以利用该终点获得新区间,缩减后容器的大小,或是获得被删除元素的个数。如下例子:
#include<iostream>
#include<list>
#include<algorithm>
#include<iterator>
using namespace std;
int main() {
list<int> coll;
for (int i = 1; i <= 6; ++i) {
coll.push_back(i);
coll.push_front(i);
}
//
cout << "pre: ";
copy(coll.begin(), coll.end(), ostream_iterator<int>(cout, " "));
cout << endl;
//end为删除所有3后的逻辑上的终点
list<int>::iterator end = remove(coll.begin(), coll.end(), 3);
//print number of resulting elements
cout << "number of removed elements: " << distance(end, coll.end()) << endl;
//remove "removed" elements
coll.erase(end, coll.end());
cout << "post: ";
copy(coll.begin(), coll.end(), ostream_iterator<int>(cout, " "));
cout << endl;
return 0;
}
输出结果:
pre: 6 5 4 3 2 1 1 2 3 4 5 6
number of removed elements: 2
post: 6 5 4 2 1 1 2 4 5 6
通常并没有必要执行erase()[其可以接受一个参数,该参数表示要从容器删除的值,并且返回删除的个数]语句,只需用remove返回的新的终点代替原来的终点即可。
copy(coll.begin(), remove(coll.begin(), coll.end(), 3), ostream_iterator<int>(cout, " "));