STL标准库algorithm中remove()函数的一个小注意事项
先给一个小程序,大家猜一下结果是什么:
1 // StandLibP112.cpp : 定义控制台应用程序的入口点。
2 //
3
4 #include "stdafx.h"
5 #include <vector>
6 #include <algorithm>
7 #include <iostream>
8
9 using namespace std;
10
11 int _tmain(int argc, _TCHAR* argv[])
12 {
13
14 vector<int> vec;
15
16 for ( int i = 0; i < 10; ++i )
17 {
18 vec.push_back(i);
19 }
20
21 copy(vec.begin(), vec.end(), ostream_iterator<int>(cout, " "));
22 cout << endl;
23
24 remove(vec.begin(), vec.end(), 3);
25 copy(vec.begin(), vec.end(), ostream_iterator<int>(cout, " "));
26 cout << endl;
27
28 return 0;
29 }
结果:
0 1 2 3 4 5 6 7 8 9
0 1 2 4 5 6 7 8 9 9
请按任意键继续. . .
为什么会是这样呢?
原因是remove()并没有改变vec的元素数量,他只是找到这个3之后,把3改变为它后续的元素,即3->4, 4->5, 5->6,...,8->9。然后9这个位置依然是9。
其实remove()的返回值是删除了vec中的3之后实际的.end()位置。我们可以按照下面这样来写:
View Code
vector<int>::iterator end = remove(vec.begin(), vec.end(), 3);
copy(vec.begin(), end, ostream_iterator<int>(cout, " "));
这样写的输出就是:
0 1 2 4 5 6 7 8 9
请按任意键继续. . .
其实,如果我们真的需要删除该元素的话,可以这样写:
vec.erase( remove(vec.begin(), vec.end(), 3), vec.end() );
remove()的注意事项讨论结束,但有一个问题缠绕着我们,为什么标准库algorithm里面的remove()不自己调用erase()呢?
下面摘抄《C++ 标准程序库》一书P114上一段话:
这个问题正好点出STL为了获取灵活性而付出的代价。透过“以迭代器为接口”,STL将数据结构和算法分离开来。然而,迭代器只不过是“容器中某一位置”的抽象概念而已。一般来说,迭代器对自己所属的容器一无所知。任何“以迭代器访问容器元素”的算法,都不得(无法)透过迭代器调用容器类别所提供的任何成员函数。