容器list使用之erase(其他容器也通用)


今天無論如何要寫點東西,算是搞清楚了一點東西吧。有點小小的成就感。
之前在程序里面使用了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進行操作是非法的,程序會出錯。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM