c++如何遍歷刪除map/vector里面的元素


對於c++里面的容器, 我們可以使用iterator進行方便的遍歷. 但是當我們通過iterator對vector/map等進行修改時, 我們就要小心了, 因為操作往往會導致iterator失效, 之后的行為都變得不可預知. 比如:

 1 #include <iostream>
 2 #include <vector>
 3  
 4 using namespace std;
 5  
 6 int main()
 7 {
 8     vector<int> a = {12, 23, 34, 45, 56, 67, 78, 89};
 9      
10     for (auto iter = a.begin(); iter != a.end(); ++iter) {
11         if (*iter > 30) {
12             a.erase(iter);
13         }
14     }
15      
16     for (const auto &element : a) {
17         cout<<element<<endl;
18     }
19      
20     return 0;
21 }
22  
23 輸出:
24  
25 12
26 23
27 45
28 67
29 89

cplusplus的reference里對 std::vector::erase 的描述是:

Iterators, pointers and references pointing to position (or first) and beyond are invalidated, with all iterators, pointers and references to elements before position (or first) are guaranteed to keep referring to the same elements they were referring to before the call.

只有刪除元素前面的iterator還保持有效, 之后的遍歷行為不可預知.

 

解決方案

對於vector, erase會返回下一個iterator, 因此我們可以使用如下的方法:

 1 #include <iostream>
 2 #include <vector>
 3  
 4 using namespace std;
 5  
 6 int main()
 7 {
 8     vector<int> a = {12, 23, 34, 45, 56, 67, 78, 89};
 9      
10     auto iter = a.begin();
11     while (iter != a.end()) {
12         if (*iter > 30) {
13             iter = a.erase(iter);
14         }
15         else {
16             ++iter;
17         }
18     }
19      
20     for (const auto &element : a) {
21         cout<<element<<endl;
22     }
23      
24     return 0;
25 }
26  
27  
28 輸出:
29  
30 12
31 23

對於map, 刪除iterator只會影響當前的iterator, 因此使用for循環就夠了, 比如:

 1 #include <iostream>
 2 #include <map>
 3  
 4 using namespace std;
 5  
 6 int main()
 7 {
 8     map<int, int> a = {{1, 12}, {2, 23}, {3, 34}, {4, 45}, {5, 56}, {6, 67}};
 9      
10     for (auto iter = a.begin(); iter != a.end(); ++iter) {
11         if (iter->second > 30) {
12             a.erase(iter);
13         }
14     }
15      
16     for (const auto &element : a) {
17         cout<<element.first<<" : "<<element.second<<endl;
18     }
19      
20     return 0;
21 }
22  
23 輸出:
24  
25 1 : 12
26 2 : 23

但是更推薦的做法是在erase前讓iterator指向下一個元素

 1 #include <iostream>
 2 #include <map>
 3  
 4 using namespace std;
 5  
 6 int main()
 7 {
 8     map<int, int> a = {{1, 12}, {2, 23}, {3, 34}, {4, 45}, {5, 56}, {6, 67}};
 9      
10     auto iter = a.begin();
11     while (iter != a.end()) {
12         if (iter->second > 30) {
13             a.erase(iter++);
14         }
15         else {
16             ++iter;
17         }
18     }
19      
20     for (const auto &element : a) {
21         cout<<element.first<<" : "<<element.second<<endl;
22     }
23      
24     return 0;
25 }
26  
27 輸出:
28  
29 1 : 12
30 2 : 23

 

 

摘自:https://www.cnblogs.com/dabaopku/p/3912662.html

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM