在vector中有三種涉及刪除的方法,第一種是vector::clear(),第二種是vector::erase(),第三種是vector::pop_back()。clear用來清空整個vector,同時將size變成0,無返回值;erase通過傳入迭代器進行刪除,既可以刪除單個元素,也可以刪除某一范圍的元素,刪除之后它將返回下一個位置的迭代器;pop_back用來刪除末尾元素,同時將size減1,無返回值。
一般來講erase用得比較多,不注意也容易踩坑,例如:
vector<int> vec{1, 4, 3, 2, 5, 2}; for(auto it = vec.begin(); it != vec.end(); it++) { if(*it < 3) { cout << "num is " << *it << endl; it = vec.erase(it); if(it == vec.end()) break; } }
這個代碼如果不在for循環里加上最后的判斷會導致錯誤,原因在於,當it指向最后一個2時,滿足刪除條件,刪除后it變成了end,然后又做了++操作,導致越界。
類似的坑還有許多,這里就不一一列舉了,總之,它們的共同點在於對vector進行刪除時都不夠優雅,需要進行一些額外的處理避免誤操作。
事實上,我們完全可以使用<algorithm>提供的remove和remove_if方法,配合erase進行刪除。這兩個方法並不是真的刪除元素,而是以覆蓋的方式將滿足刪除條件的元素移到容器最后(它們具體的實現方式很有意思,但是這里從略,總之有兩點:1)它們並沒有真的刪除元素;2)它們使用了“覆蓋”的方式,將要刪除的元素移到最后,因此這些元素可能因為被覆蓋過而發生改變,但這已經不重要了),然后返回指向第一個要刪除位置的迭代器。這樣一來,刪除就優雅多了,例如:
vec.erase(remove(vec.begin(), vec.end(), 3), vec.end());
如果再用上lambda,看起來會更酷:
vec.erase(remove_if(vec.begin(), vec.end(), [](int x){return x == 3;}), vec.end());
原文鏈接:
參考:
C++中Vector.erase()刪除某一元素的正確用法
https://en.cppreference.com/w/cpp/algorithm/remove