Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1670382
  • 博文数量: 695
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 4027
  • 用 户 组: 普通用户
  • 注册时间: 2013-11-20 21:22
文章分类

全部博文(695)

文章存档

2018年(18)

2017年(74)

2016年(170)

2015年(102)

2014年(276)

2013年(55)

分类: C/C++

2014-02-24 22:27:39

容器list使用之erase

(2011-01-11 10:46:02)
标签:

容器

list

erase

杂谈

分类: C++
       今天无论如何要写点东西,算是搞清楚了一点东西吧。有点小小的成就感。
       之前在程序里面使用了list容器,其中用到了erase()函数,之前一直没出现问题,这两天突然莫名奇妙。花了点时间,搞清楚了erase()函数的机理。
       常用的删除容器中元素的方法是如下(方法1):
      list< int> List;
      list< int>::iterator iter;
      for( iter = List.begin(); iter != List.end(); )
      {
            if(1)  
            {
               iter = List.erase( iter );
            }
            else
            {
               iter++;
            }
      }

      也可以这样写(方法2):
      list< int> List;
      list< int>::iterator iter;
      for( iter = List.begin(); iter != List.end(); )
      {
            if(1)  
            {
               List.erase( iter++ );
            }
            else
            {
               iter++;
            }
      }

     有一种错误的写法(注意同方法2比较)
     list< int> List;
      list< int>::iterator iter;
      for( iter = List.begin(); iter != List.end(); )
      {
            if(1)  
            {
               List.erase( iter );
            }

            iter++;
      }

     我们看一下erase()函数的源代码(仅列出release下的代码)。
        iterator erase(iterator _Where)
        {    // erase element at _Where
        _Nodeptr _Pnode = (_Where++)._Mynode();

        if (_Pnode != _Myhead)
            {    // not list head, safe to erase
            _Nextnode(_Prevnode(_Pnode)) = _Nextnode(_Pnode);
            _Prevnode(_Nextnode(_Pnode)) = _Prevnode(_Pnode);
            this->_Alnod.destroy(_Pnode);
            this->_Alnod.deallocate(_Pnode, 1);
            --_Mysize;
            }
        return (_Where);
        }

函数在返回的时候,是返回当前迭代器的下一个节点。所以当 iter = List.erase( iter ); 执行以后,迭代器自动指向了下一个元素。而对于入参中的iter,所指的地址已经被销毁,所以写的时候,应该注意加上前面的iter =
那另外的一种写法,List.erase( iter++ ); 为什么也是对的呢?
这里研究了一下,这里需要讲一下++运算符的操作。(惭愧啊,++使用了这么多年,居然现在才搞明白)
        _Myt_iter& operator++()   
            {    // preincrement
            ++(*(_Mybase_iter *)this);
            return (*this);
            }

        _Myt_iter operator++(int) 
            {    // postincrement
            _Myt_iter _Tmp = *this;
            ++*this;
            return (_Tmp);
            }

++实际上可以看做是一个函数。
对于++在后的情况(例如i++),函数在运行的时候,将运算的数据i已经改变,但是函数的返回值是操作之前的数据,所以在我们看来,i++好像是先进行了i的读取,才+1。

回到迭代器,List.erase( iter++ );就没有问题了。

对于那种错误的方法,List.erase( iter );在执行以后,iter所指的对象已经被销毁,所以再对iter进行操作是非法的,程序会出错。

阅读(801) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~