1. 程式人生 > >我不會程式設計,但不是完全不會,我會一點點

我不會程式設計,但不是完全不會,我會一點點

STL中list的erase用法

erase的作用是,使作為引數的迭代器失效,並返回指向該迭代器下一引數的迭代器。

如下:

list<DotSource>ParticleSystem;

list<DotSource>::iteratorpointer;

if(pointer->dead == true)
{
   pointer =ParticleSystem.erase(pointer);
}

有一段關於錯誤使用erase的程式

#include<stdio.h>
#include<list>
using namespace std;
int main()
{
 std::list<int>test_list;
 std::list<int>::iteratortest_list_it;

  test_list.push_back(1);

  test_list_it = test_list.begin();
  for(;test_list_it !=test_list.end();test_list_it++)

  {
  test_list.erase(test_list_it);
  }
}

問題:該程式不能跳出迴圈

原因:test_list.erase(test_list_it);每次做erase時都有可能使迭代器失效,test_list_it++就發生錯誤了。可以參見effectivestl一書。所有容器做erase操作時都有可能使迭代器失效。

改為:

for(;test_list_it != test_list.end();)

  {
  test_list.erase(test_list_it++);
  }

or

for(;test_list_it != test_list.end();)

  {
std::list<int>::iteratoriter_e=test_list_it++;
  test_list.erase(iter_e);
  }

注意:

for(;test_list_it != test_list.end();test_list_it++;)

  {
std::list<int>::iteratoriter_e=test_list_it;
  test_list.erase(iter_e);
  }
這樣任然是錯誤的,原因是:iter_e=test_list_it是指標值的複製,它倆其實指向同一個位置,所以iter_e失效那麼test_list_it也會失效,所以test_list_it++就會有問題
如果是:

for(;test_list_it != test_list.end();)
{
std::list<int>::iteratoriter_e=test_list_it++;
test_list.erase(iter_e);
}
則沒有問題。

--------------------------------------------------------分割線-----------------------------------------------------------------------------

vector::erase():從指定容器刪除指定位置的元素或某段範圍內的元素 vector::erase()方法有兩種過載形式

如下:

iterator erase(   iterator _Where);

1.iterator erase(   iterator _First,   iterator _Last);

如果是刪除指定位置的元素時: 返回值是一個迭代器,指向刪除元素下一個元素; 如果是刪除某範圍內的元素時:返回值也表示一個迭代器,指向最後一個刪除元素的下一個元素;

<轉>STL vector的erase

以前就發現了vector中的erase方法有些詭異(^_^),稍不注意,就會出錯。今天又一次遇到了,就索性總結一下,尤其是在迴圈體中用erase時,由於vector.begin() 和vector.end()是變化的,因此就引入了錯誤的可能性。

vector<int> veci;
veci.push_back(1);
veci.push_back(2);
veci.push_back(3);
veci.push_back(4);
veci.push_back(5);
veci.push_back(3);
veci.push_back(2);
veci.push_back(3);

for(vector<int>::iterator iter=veci.begin(); iter!=veci.end(); iter++)
{
      if( *iter == 3)
             veci.erase(iter);
}

乍一看這段程式碼,很正常。其實這裡面隱藏著一個很嚴重的錯誤:當veci.erase(iter)之後,iter就變成了一個野指標,對一個野指標進行 iter++ 是肯定會出錯的。

檢視MSDN,對於erase的返回值是這樣描述的:An iterator that designates the first element remaining beyond any elements removed, or a pointer to the end of the vector if no such element exists,於是改程式碼:

for(vector<int>::iterator iter=veci.begin(); iter!=veci.end(); iter++)
{
      if( *iter == 3)
             iter = veci.erase(iter);
}

這段程式碼也是錯誤的:1)無法刪除兩個連續的"3"; 2)當3位於vector最後位置的時候,也會出錯(在veci.end()上執行 ++ 操作)

正確的程式碼應該為:

for(vector<int>::iterator iter=veci.begin(); iter!=veci.end(); )
{
     if( *iter == 3)
          iter = veci.erase(iter); //返回值指向刪除元素的下一個元素       else
            iter ++ ;
}