vector中的erase用法注意事項
以前就發現了vector中的erase方法有些詭異(^_^),稍不注意,就會出錯。今天又一次遇到了,就索性總結一下,尤其是在迴圈體中用erase時,由於vector.begin() 和vector.end()是變化的,因此就引入了錯誤的可能性。
erase的函式原型有兩種形式:
iterator erase(iterator position);
iterator erase(iterator first, iterator last);
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(); ) //for迴圈中不要iter++
{
if( *iter == 3)
iter = veci.erase(iter);
else
iter ++ ;
}
或者這樣寫
for(vector<int>::iterator iter=veci.begin(); iter!=veci.end(); ) //for迴圈中不要iter++
{
if( *iter == 3)
veci.erase(iter++); //注意:一定是iter++,不是++iter。
//刪除之後,原來那個iter就無效了,需要向後移動一位,否則會出現崩潰
else
iter ++ ;
}
為了避免對野指標進行操作,另一種解決方法如下:
vector<int>::iterator itor2;
for(vector<int>::iterator iter=veci.begin(); iter!=veci.end(); )
{
if( *iter == 3)
{
itor2=iter;
veci.erase(itor2);
}
else
iter ++ ;
}
要解決無法刪除兩個連續的3的另一種方法如下:
vector<int> veci;
veci.erase(remove(veci.begin(),veci.end(),6),veci.end());
這裡用到了remove()函式,
注:remove是個stl的通用演算法std::remove(first,last,val)移除[first, last)範圍內等於val的元素在vector裡面用就類似於iter = std::remove(vec.begin(), vec.end(), val)但這個函式只是把val移到vec的末尾,並不真正刪除真正刪除還是要呼叫一次erase函式