最近在刷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也存在這種問題,解決方法同樣