容器删除元素erase,迭代器失效的问题

来源:互联网 发布:linux系统数据库备份 编辑:程序博客网 时间:2024/05/10 14:28

转载链接:http://blog.csdn.net/hlsdbd1990/article/details/46363433  (这篇写的很全面很详细,转载的博主是个女生,厉害,比较有用所以转载收藏下)


简介

看一下9.5节容器之间的区别—-list类似于链表,容易增删改,queue是两端增删改容易。,所以删除时,用到最多的容器时list

1.删除第一个或最后一个元素—–pop_front 和pop_back 函数,函数返回void

2.删除容器内的一个或一段元素—–erase函数,erase都返回一个迭代器,它指向被删除的元素后面的元素

3.删除容器内所有的元素—clear函数

4. 注意:在删除元素后迭代器会失效,因此一定要对迭代器重新赋值。另外,erase函数返回一个迭代器,指向被删除元素的下一个元素。因为在for语句头中要对迭代器加1,所以在if语句中将迭代器减1,以免漏掉需要处理的元素。

===========================================================================================================

一、删除元素—–queue和list容器

前面提到过使用insert操作在容器的任何位置插入元素,并支持特定的push_back和push_front 操作在容器首部或尾部插入新元素。 
类似的,容器提供了erase操作和特定的pop_front和pop_back操作来删除容器内的元素。

这里写图片描述

1. 删除第一个或最后一个元素pop_front 和pop_back 函数—list可以,queue也可以

  • pop_front 和pop_back函数用于删除容器内的第一个和最后一个元素。但vector容器类型不支持pop_front操作。这些操作删除指定的元素并返回void;

  • pop_front 经常与front操作配套使用,实现以栈的方式处理容器

  • pop_front 和pop_back函数的返回值并不是删除的元素值,而是void。要获取删除的元素值,则必须在删除元素之前调用front或back函数。

while(!ilist.empty()){   process(ilist.front());//获取要删除的元素   ilist.pop_front();//删除第一个元素}
  • 1
  • 2
  • 3
  • 4
  • 5

2.删除容器内的一个或一段元素erase操作—list容器

  • 删除一个或一段元素更通用的方法是erase操作。

  • 该操作有两个版本:删除由一个迭代器指向的单个元素,删除由一对迭代器标记的一段元素。erase的这两种形式都返回一个迭代器,它指向被删除的元素后面的元素。

  • 必须确保用作参数的迭代器或迭代器范围是有效的。

  • * 通常要在容器中找到要删除的元素后,才使用erase操作。寻找一个指定元素的最简单方法是使用标准库的find算法。*

  • find算法在后面的11.1节还会介绍,为了使用find函数或其他泛型算法,在编程时,必须将algorithm头文件包含进来。

  • find函数需要一对标记查找范围的迭代器以及一个在该范围内查找的值做参数,查找完成后,该函数返回一个迭代器,它指向具有指定值的第一个元素,或超出末端的下一个位置。

string searchValue("Quasimodo");//定义一个string对象list<string>::iterator iter=find(slist.begin(),slist.end(),searchValue);if(iter!=slist.end())    slist.erase(iter);//是iter,不是*iter//注意:在删除元素之前,必须确保迭代器是不是end迭代器。使用erase操作删除单个元素必须确保该元素确实存在------如果删除指向超出末端的下一个位置的迭代器,那么erase操作的行为未定义
  • 1
  • 2
  • 3
  • 4
  • 5

3.删除容器内所有的元素—clear函数

slist.clear();//删除所有元素slist.erase(slist.begin(),slist.end());同上//erase 函数的迭代器对版本提供了删除一部分元素的功能:list<string>::iterator elem1,elem2;elem1=find(slist.begin(),slist.end(),val1);//elem1指向val1elem2=find(elem1,slist.end(),val2);//elem2指向val2slist.erase(elem1,elem2);//删除elem1到elem2之间的所有元素,但不包括elem2指向的元素
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • erase、pop_front、pop_back函数使指向被删除元素的所有迭代器失效。对于vector容器,指向删除点后面的元素的迭代器通常也会失效,而对于queue容器,如果删除时不包括第一个元素或最后一个元素,那么deque容器相关的所有迭代器都会失效
//习题9.25//需要删除一段元素时,如果val1和val2相等,那么程序会怎样?其中一个不存在,程序会怎样?//解答//相等,那么不会删除任何元素。//其中一个不存在,或两个都不存在,则会发生运行错误。
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
//习题9.26#include <iostream>#include<string>#include<cctype>#include<vector>#include<list>using namespace std;int main(){int ia[]={0,1,1,2,3,4,5,8,13,21,55,89};vector<int> ivec(ia,ia+11);list<int> ilst(ia,ia+11);for(list<int>::iterator lit=ilst.begin();lit!=ilst.end();lit++){if(*lit%2!=0){    lit=ilst.erase(lit);//删除元素    --lit;}cout<<*lit;}cout<<endl;for(vector<int>::iterator vit=ivec.begin();vit!=ivec.end();vit++){if(*vit%2==0){    vit=ivec.erase(vit);//删除元素    --vit;//迭代器重新赋值,进行回退,指向被删除元素的前一个元素。}cout<<*vit;}    return 0;}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40

注意:在删除元素后迭代器会失效,因此一定要对迭代器重新赋值。另外,erase函数返回一个迭代器,指向被删除元素的下一个元素。因为在for语句头中要对迭代器加1,所以在if语句中将迭代器减1,以免漏掉需要处理的元素。