C++遍歷刪除元素
轉自:http://zencoder.info/2019/10/11/erase-element-from-container/
今天看到一個patch fix從std::map
中遍歷刪除元素導致crash問題,突然意識到自己對如何正確地從map
等C++容器中刪除元素也沒有很牢固清醒的認知。重新梳理了下這塊的正確做法,記錄在此,以備后忘。
基礎知識
C++的容器按存儲方式分為兩類:
- 以數組形式存儲的順序容器,如:
vector,deque
- 以不連續節點形式存儲的容易,如:
list, set, map
在使用erase
方法遍歷刪除元素時,需要注意一些問題,否則就會踩坑。
對容器進行增刪元素操作,可能會使迭代器失效。如果一個元素已經被刪除,則其對應的迭代器會失效,不應該再被使用;否則會導致程序無定義的行為,基本上就會掛了。
正確的遍歷刪除方法
對于遍歷刪除map、list、set可以使用下面2種正確方法:
1. 使用刪除元素之前的迭代器定義下一個元素,建議使用的方式
for (auto it=mymap.begin(); it!=mymap.end();) {if (it->first == target) {mymap.erase(it++); //here is the key} else {it++;}
}
2. 使用erase()返回下一個元素的迭代器
for (auto it=mymap.begin(); it!=mymap.end();) {if (it->first == target) {it = mymap.erase(it);} else {it++;}
}
注意:在對 vector、deque遍歷刪除元素時,可以通過erase的返回值來獲取下一個元素的位置,也就是上面的第2種方法;但不能使用上面的第1種方法來遍歷刪除。
錯誤的遍歷刪除方法
把經常會踩坑的錯誤的寫法貼在下面,作為警示!
下面的寫法是錯誤的!下面的寫法是錯誤的!下面的寫法是錯誤的!
for (auto it=mymap.begin(); it!=mymap.end(); it++) {if (it->first == target) {mymap.erase(it); //這里的寫法是錯誤的,錯誤的,錯誤的!!!//it對應的元素已經被刪除,it迭代器失效,在for循環中執行it++會導致未定義行為}
}
下面的寫法對vector是錯誤的!下面的寫法對vector是錯誤的!下面的寫法對vector是錯誤的!
for (auto it=myvector.begin(); it!=myvector.end();) {if (*it == target) {myvector.erase(it++); //對vector不能工作} else {it++;}
}