STL中erase()的陷阱

最近在刷stl源碼剖析這本書時,對於vector的erase()函數引發了個人注意windows

在刪除單個元素時是這樣定義的:函數

iterator erase(iterator position)
{   
if(position+1!=end())
  {     copy(position
+1,finish,postion);
  }   
--finish;   destroy(finish);   return position; }

erase()將position+1後面的元素拷貝給了position,並將最後一個位置-1,那麼刪除後的vectors是否是一個新容器,書上沒說,可是容器的長度變了,返回的指針仍是position。指針沒變。erase(it)後,iterator不變,可是裏面的元素已是下一個,若是須要指向刪除元素的前面一個元素的迭代器iterator就要-1。post

for(vector<int>::iterator it=arr.begin(); it!=arr.end(); it ++) { if(* it == 0) { arr.erase(it); //  } }

該方法中利用了後++的特色,這個時候執行mapTest.erase(it++);這條語句分爲三個過程spa

 

一、先把it的值賦值給一個臨時變量作爲傳遞給erase的參數變量指針

二、由於參數處理優先於函數調用,因此接下來執行了it++操做,也就是it如今已經指向了下一個地址。code

三、再調用erase函數,釋放掉第一步中保存的要刪除的it的值的臨時變量所指的位置。blog

 

iteratort存儲的不是新的vector,iterator爲野指針,繼續++就會報錯,此時iterator應該若是想繼續迭代,應該從新獲取vector:源碼

方法一it

for(vector<int>::iterator it=arr.begin(); it!=arr.end(); ){ if(* it == 0) { it = arr.erase(it); } else { ++it; } }

 

方法二io

for(vector<int>::iterator it=arr.begin(); it!=arr.end(); ){ if(* it == 0) { arr.erase(++it); } else { ++it; } }

雖然上面兩種方法達到了一個相同的效果,可是,更提倡使用第二種,第一種方法只適用於windows平臺,並非標準庫的支持

同理,map也存在這種問題,解決方法同樣

相關文章
相關標籤/搜索