STL中的容器按存储方式分为两类,一类是按以数组形式存储的容器(如:vector 、deque);另一类是以不连续的节点形式存储的容器(如:list、set、map)。在使用erase方法来删除元素时,需要注意一些问题。
      在 使用 list、set 或 map遍历删除某些元素时可以这样使用:

正确使用方法1      std::list< int> List;
      std::list< int>::iterator itList;
      for( itList = List.begin(); itList != List.end(); )
      {
            if( WillDelete( *itList) )
            {
               itList = List.erase( itList);
            }
            else
               itList++;
      }

正确使用方法2      std::list< int> List;
      std::list< int>::iterator itList;
      for( itList = List.begin(); itList != List.end(); )
      {
            if( WillDelete( *itList) )
            {
               List.erase( itList++);
            }
            else
               itList++;
      }

下 面是两个错误的使用方法:

错误使用方法1      std::list< int> List;
      std::list< int>::iterator itList;
      for( itList = List.begin(); itList != List.end(); itList++)
      {
            if( WillDelete( *itList) )
            {
               List.erase( itList);
            }
      }


错误使用方法2      std::list< int> List;
      std::list< int>::iterator itList;
      for( itList = List.begin(); itList != List.end(); )
      {
            if( WillDelete( *itList) )
            {
               itList = List.erase( ++itList);
            }
            else
               itList++;
      }

正 确使用方法1:通过erase方法的返回值来获取下一个元素的位置
      正确使用方法2:在调用erase方法之前先使用 “++”来获取下一个元素的位置
      错误使用方法1:在调用erase方法之后使用“++”来获取下一个元素的位置,由于在调用 erase方法以后,该元素的位置已经被删除,如果在根据这个旧的位置来获取下一个位置,则会出现异常。
      错误使用方法2:同上。

这 里“++”运算符与我们平常的理解刚好相反,erase( itList++) 是先获取下一个元素的位置在删除; erase( ++itList) 是删除以后再获取下一个元素的位置。

在使用 vector、deque遍历删除元素时,也可以通过erase的返回值来获取下一个元素的位置:
正确使用方法      std::vector< int> Vec;
      std::vector< int>::iterator itVec;
      for( itVec = Vec.begin(); itVec != Vec.end(); )
      {
            if( WillDelete( *itVec) )
            {
                 itVec = Vec.erase( itVec);
            }
            else
               itList++;
      }      
      注 意:vector、deque 不能像上面的“正确使用方法2”的办法来遍历删除。

假如有一个列表 ShipList,里面的内容是0、1、2、3...9, 如果要从中删除那些取余3后为0或为1的数,删除后应该得出的结果是 2、5、8。 
但如果是这样操作: 
std::<int >::iterator it; 
for( it = ShipList.begin(); it != ShipList.end(); it++) 

if( (*it) % 3 == 0 || (*it) % 3 == 1) 
ShipList.erase( it++); 

这样的话会有两个问题,一个是得出的结果是 1、2、4、5、7、8(没有删除取余3后等于1的数);另外一个问题是当执行到列表中最后一个元素(即ShipList.end() - 1 )时,迭代器可能还会执行两次“++”,如果是这样那么it就到达了 ShipList.end() + 1 的位置,这样也会报错。

erase( itList++) 是先获取下一个元素的位置再删除; erase( ++itList) 是删除以后再获取下一个元素的位置。 
我认为,erase(itList++)是itList先传递值给erase(),然后再自增;
erase(++itList) 是先自增,然后再把自增后的值传递给erase(),这个是出错的根源。

from:
http://www.cppblog.com/Herbert/archive/2009/01/08/70479.html

STL中用erase()方法遍历删除元素的更多相关文章

  1. STL中用erase()方法遍历删除元素 .xml

    pre{ line-height:1; color:#f0caa6; background-color:#2d161d; font-size:16px;}.sysFunc{color:#e54ae9; ...

  2. List怎么遍历删除元素

    public static void main(String[] args) {  List<String> list = new ArrayList<String>();   ...

  3. C++ vector 删除一个指定元素 和 find 一个指定元素以及遍历删除、 map遍历删除元素和删除find到的元素

    vector: 1.delete element 转载:http://www.cnblogs.com/xudong-bupt/p/3522457.html #include <vector> ...

  4. java中List遍历删除元素-----不能直接 list.remove()

    https://blog.csdn.net/github_2011/article/details/54927531 这是List接口中的方法,List集合调用此方法可以得到一个迭代器对象(Itera ...

  5. python中list用法及遍历删除元素

    列表(list)是python的基本数据结构,list中每一个元素都分配一个位置索引,可以通过索引访问元素值,list不要求数据项有相同的数据类型. list初始化 list由一个方括号加内部由逗号分 ...

  6. HashMap和List遍历方法总结及如何遍历删除元素

    https://blog.csdn.net/demohui/article/details/77748809

  7. Python自学:第三章 使用方法pop()删除元素

    motorcycle = ["honda", "yamaha", "suzuki"] last_owned = motorcycle.pop ...

  8. 解决List遍历删除元素提示ConcurrentModificationException

    JDK1.8提供新的API  ===>  removeIf public static void main(String[] args) { List<String> list = ...

  9. STL的erase()陷阱-迭代器失效总结

    下面材料整理自Internet&著作. STL中的容器按存储方式分为两类,一类是按以数组形式存储的容器(如:vector .deque):另一类是以不连续的节点形式存储的容器(如:list.s ...

随机推荐

  1. 将Eclipse代码导入到Android Studio的两种方式

    转: http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0104/2259.html 说到使用Android Studio,除了新建 ...

  2. Flink Program Guide (4) -- 时间戳和Watermark生成(DataStream API编程指导 -- For Java)

    时间戳和Watermark生成 本文翻译自Generating Timestamp / Watermarks --------------------------------------------- ...

  3. 【转】MUD教程--巫师入门教程4

    我们再次复习一下clean_up()函数返回1的含义,如果clean_up()函数返回1,则MUDOS在这一次的调用时不会做其的任何举动,但到了下一次想调用的时间里,还将再次调用这个对象的clean_ ...

  4. mysql性能优化学习笔记(2)如何发现有问题的sql

    一.使用mysql慢查询日志对有效率问题的sql进行监控      1)开启慢查询       show variables like ‘slow_query_log’;//查看是否开启慢查询日志   ...

  5. Oracle字符编码

    .检查服务器编码: 执行SQL语法: Java代码 select * from v$nls_parameters; 或 Java代码 select * from nls_database_parame ...

  6. linux中fork创建进程讲解(转)

    大家知道Linux中创建子进程的一个很好的方法是函数调用fork,但是很多初学者对fork的理解上可能有点困难.我们举个例子来看看fork的用法吧.         大家用fork的时候记住fork是 ...

  7. Mactype 解决字体出现剃尾

    使用mactype之后, 发现windows字体的效果改善了好多.但作为程序员, 天天和各种文本工具打交道.最近发现PHPStorm中的有些等宽字体会出现剃尾的现象.特别是 {} [] ()这些字符, ...

  8. 使用CocoaPods找不到头文件解决方法

    Project->Info->Configurations

  9. Dreamweaver PHP代码护眼配色方案

    结果展示 [1]主菜单选择编辑->首选项.在分类中选择"字体".设置代码视图的字体为Courier New [2]在分类中选择 "代码颜色",点击 &qu ...

  10. kindeditor更改图片上传时网络图片的路径

    当我们想要使用kindeditor的图片上传功能时,有两种选择图片方式,一种是本地选择,一种是在图片空间中选择,图片空间的默认地址是server上的/kindeditor/attached/image ...