vector使用十分方便,可以存放任意類型數據結構。有時候我們會在vector中存放對象指針等,在刪除某個元素的時候,我們還需要釋放相應的內存。
本文主要談一下erase方法,尤其是在循環體中使用erase方法,需要注意是否存在隱性問題。
erase的函數原型有兩種形式:
iterator erase(iterator position); iterator erase(iterator first, iterator last);
例如有一個類A,
class A { public: int id; A(void); ~A(void); };
定義vector<A*> vec
for (int i=0; i<10; i++) { A *p = new A(); p->id = i; vec.push_back(p); }
下面要刪除vec中id爲5的元素:
for(vector<A*>::iterator iter=vec.begin(); iter!=vec.end(); iter++) { if(5 == (*iter)->id) { delete *iter; veci.erase(iter); } }
初看這段代碼沒什麼問題,實際上其中存在很大的問題;當調用erase方法後,iter就變成了一個野指針,繼續循環iter++就出錯了。
那我們繼續修改代碼:
for(vector<A*>::iterator iter=vec.begin(); iter!=vec.end(); iter++) { if(5 == (*iter)->id) { delete *iter; iter = veci.erase(iter); } }
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
仔細閱讀上面的代碼實際上也有問題,首先代碼不能刪除連續兩個爲5的元素,因爲刪除第一個之後,iter指向第二個,自增後,就指向了第二個後面了;其次如果元素5位於vector最後,刪除後iter自增也會出錯。
那麼正確的寫法可以如下:
for(vector<A*>::iterator iter=vec.begin(); iter!=vec.end(); ) { if(5 == (*iter)->id) { delete *iter; iter = veci.erase(iter); } else { iter++; } }
這樣就可以解決連續兩個相同元素的問題,同時將要刪除的元素位於最後的話,也不會有問題,因爲刪除後,erase返回vector.end()。