使用iterator 遍历时,删除其中一个出了问题,结果是删除了一个以后 不能再用自增了
一直对vector的删除操作不太熟悉,现整理下。其中前三部分先补充一些相关知识,然后第四部分给出示例代码。
一、关于Vector的earse方法
iterator erase ( iterator position ); iterator erase ( iterator first, iterator last );
Erase elements
This effectively reduces the vector size by the number of elements removed, calling each element's destructor before.
Because vectors keep an array format, erasing on positions other than the vector end also moves all the elements after the segment erased to their new positions, which may not be a method as efficient as erasing in other kinds of sequence containers ( deque, list).
This invalidates all iterator and references to elements after position or first.
Parameters
All parameters are of member type iterator, which in vector containers are defined as a random access iterator type.-
position
- Iterator pointing to a single element to be removed from the vector. first, last
- Iterators specifying a range within the vector to be removed: [first,last). i.e., the range includes all the elements between first and last, including the element pointed by first but not the one pointed by last.
Return value
A random access iterator pointing to the new location of the element that followed the last element erased by the function call, which is the vector end if the operation erased the last element in the sequence.
=======================================我是勤劳的分割线=========================================
二、关于remove_if ( <algorithm>)
ForwardIterator remove_if ( ForwardIterator first, ForwardIterator last,
Predicate pred );
Remove elements from range
The behavior of this function template is equivalent to:
1 2 3 4 5 6 7 8 9 | |
Return value
A forward iterator pointing to the new end of the sequence, which now includes all the elements for which pred was false.
=======================================我是勤劳的分割线=========================================
三、关于find()函数
function template
<algorithm>
template <class InputIterator, class T> InputIterator find ( InputIterator first, InputIterator last, const T& value );
Find value in range
The behavior of this function template is equivalent to:
1 2 3 4 5 6 | |
Return Vaule: An iterator to the first element in the range that matches value.
If no element matches, the function returns last.
=======================================我是勤劳的分割线=========================================
四、 下面以代码来演示vector的删除元素的方法,其中用到三个宏DEMO1, DEMO2, DEMO3的目的是使得一个文件能一次多演示几个例子。演示不同的DEMO时,只要在编译时加入 -D 宏名字 即可。如要演示DEMO2时,按如下方法编译:
g++ VectorDelete.cpp -o vec -D DEMO2
001 /*
002 DATE: 2010.6.25
003 内容:关于vector的遍历删除
004 任何改变 vector 长度的操作都会使已存在的迭代器失效。例如,在调用 push_back 之后,就不能再信赖指向 vector 的迭代器的值了。
005 一个原则:对vector只要做了删除或是增加动作,就要示迭代器已经无效,必须重新从vector对象获取新的迭代器的值,而不能用临时变量、后缀自增等方法
006 */
007 #include <iostream>
008 #include <vector>
009 #include <string>
010 #include <cstring>
011 #include <list>
012 #include <algorithm> //to use remove_if
013 using namespace std;
014
015
016 typedef vector<int> V;
017 typedef vector<int>::iterator VIT;
018 typedef list<int> L;
019 typedef list<int>::iterator LIT;
020 V v;
021 L lis;
022
023
024 class InList
025 {
026 public:
027 InList(list<int> &lis):li(lis){}
028
029 bool operator()(int n)
030 {
031 return find(li.begin(), li.end(), n)!=li.end();
032 }
033 private:
034 list<int> &li;
035 };
036
037
038 int main()
039 {
040 for(int i=0; i<10; ++i) // 初始化v: 0 1 2 3 4 5 6 7 8 9
041 v.push_back(i);
042 for(int i=0; i<5; ++i) // 初始化lis:0 1 2 3 4
043 lis.push_back(i);
044
045 VIT it;
046 //cout<<endl<<v.end()-v.begin()<<endl; //vector容器的iterator是支持加减操作的,这在其他类型的迭代器中很少见
047
048 #ifdef DEMO1
049 //遍历删除v中不等于3的元素的正确方法
050 for(it=v.begin(); it!=v.end();)
051 {
052 if(*it != 3)
053 {
054 //将it赋值为erase()的返回值,它指向the new location of the element that followed the last element erased
055 it = v.erase(it);
056 }
057 else
058 ++it;
059 }
060 for(it=v.begin(); it!=v.end(); ++it)
061 cout<<*it<<endl;
062 #endif
063
064 #ifdef DEMO2
065 //DEMO2的功能: 在v中,删除那些在v和在lis中同时存在的元素,不使用remove_if
066 it = v.begin();
067 VIT del = it;
068 for(; it!=v.end(); ++it)
069 {
070 if(find(lis.begin(),lis.end(),*it) == lis.end())
071 {
072 *del++ = *it;
073 }
074 }//此时,del指向A iterator pointing to the new end of the sequence,which now includes all the elements which is not in lis.
075 //整个v变为 5 6 7 8 9 5 6 7 8 9,其中,del指向第二个5
076 v.erase(del, v.end());
077 for(it=v.begin(); it!=v.end(); ++it)
078 cout<<*it<<endl;
079 #endif
080
081 #ifdef DEMO3
082 //DEMO2的功能: 在v中,删除那些在v和在lis中同时存在的元素,使用remove_if
083
084 /*
085 //如果先单独运行remove_if,则v会变为5 6 7 8 9 5 6 7 8 9
086 //即其前五个值由0 1 2 3 4 变为5 6 7 8 9,这与remove_if的实现有关
087 remove_if(v.begin(), v.end(), InList(lis));
088 for(it=v.begin(); it!=v.end(); ++it)
089 cout<<*it<<endl;
090 */
091
092 //remove_if的返回值是A forward iterator pointing to the new end of the sequence,
093 //which now includes all the elements for which InList(lis) was false.
094 v.erase(remove_if(v.begin(), v.end(), InList(lis)), v.end());
095 for(it=v.begin(); it!=v.end(); ++it) //此时v变为5 6 7 8 9, 0 1 2 3 4被删除
096 cout<<*it<<endl;
097 #endif
098
099 return 0;
100 }