c++ vector遍历删除元素 出错的问题

使用iterator 遍历时,删除其中一个出了问题,结果是删除了一个以后 不能再用自增了

c++ vector遍历删除元素
一直对vector的删除操作不太熟悉,现整理下。其中前三部分先补充一些相关知识,然后第四部分给出示例代码。
一、关于Vector的earse方法
iterator erase ( iterator position );
iterator erase ( iterator first, iterator last );

Erase elements

Removes from the vector container either a single element ( position) or a range of elements ( [first,last) ).

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 ( dequelist).

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

Removes from the range  [first,last) the elements for which  pred applied to its value is true, and returns an iterator to the new end of the range, which now includes only the values for which  pred was false.

The behavior of this function template is equivalent to:

1
2
3
4
5
6
7
8
9
template < class ForwardIterator, class Predicate >
  ForwardIterator remove_if ( ForwardIterator first, ForwardIterator last,
                              Predicate pred )
{
  ForwardIterator result = first;
  for ( ; first != last; ++first)
    if (!pred(*first)) *result++ = *first;
  return result;
}
Notice that this function does not alter the elements past the new end, which keep their old values and are still accessible.

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

Returns an iterator to the first element in the range [first,last) that compares equal to value, or last if not found.

The behavior of this function template is equivalent to:

1
2
3
4
5
6
template<class InputIterator, class T>
  InputIterator find ( InputIterator first, InputIterator last, const T& value )
  {
    for ( ;first!=last; first++) if ( *first==value ) break;
    return first;
  }

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=0i<10++i// 初始化v: 0 1 2 3 4 5 6 7 8 9
041                 v.push_back(i);
042         for(int i=0i<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 }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值