首先咱們講遍歷std::map, 大部分人都能寫出第一種遍歷的方法,但這種遍歷刪除的方式並不太安全。ios
第一種 for循環變量:緩存
#include<map> #include<string> #include<iostream> using namespace std; int main() { map<int,string*> m; m[1]= new string("1111111111111111"); m[2]= new string("2222222222222222"); m[3]= new string("3333333333333333"); m[4]= new string("4444444444444444"); m[0]= new string("5555555555555555"); map<int,string*>::iterator it; for(it=m.begin();it!=m.end();++it) { cout<<"key: "<<it->first <<" value: "<<*it->second<<endl; delete it->second; m.erase(it); } return 0; }
結果以下:安全
key: 0 value: 5555555555555555
key: 1 value: 1111111111111111
key: 2 value: 2222222222222222
key: 3 value: 3333333333333333
key: 4 value: 4444444444444444函數
第二種while循環的遍歷:spa
#include <map> #include <string> #include <iostream> #include <cstring> using namespace std; struct ltstr { bool operator()(const char* s1, const char* s2) const { return strcmp(s1, s2) < 0; } }; int main() { map<const char*, int, ltstr> ages; ages["Homer"] = 38; ages["Marge"] = 37; ages["Lisa"] = 8; ages["Maggie"] = 1; ages["Bart"] = 11; while( !ages.empty() ) { cout << "Erasing: " << (*ages.begin()).first << ", " << (*ages.begin()).second << endl; ages.erase( ages.begin() ); } }
運行結果:code
Erasing: Bart, 11
Erasing: Homer, 38
Erasing: Lisa, 8
Erasing: Maggie, 1
Erasing: Marge, 37blog
第三種更安全的for 循環遍歷:進程
#include<map> #include<string> #include<iostream> using namespace std; int main() { map<int,string*> m; m[1]= new string("1111111111111111"); m[2]= new string("2222222222222222"); m[3]= new string("3333333333333333"); m[4]= new string("4444444444444444"); m[0]= new string("5555555555555555"); map<int,string*>::iterator it; for(it=m.begin();it!=m.end();) { cout<<"key: "<<it->first <<" value: "<<*it->second<<endl; delete it->second; m.erase(it++); } return 0; }
運行結果與第一種方式相同,不過這種刪除方式也是STL源碼一書中推薦的方式,分析 m.erase(it++)語句,map中在刪除iter的時候,先將iter作緩存,而後執行iter++使之指向下一個結點,再進入erase函數體中執行刪除操做,刪除時使用的iter就是緩存下來的iter(也就是當前iter(作了加操做以後的iter)所指向結點的上一個結點)。源碼
根據以上分析,能夠看出(m.erase(it++) )和(m.erase(it); iter++; )這個執行序列是不相同的。前者在erase執行前進行了加操做,在it被刪除(失效)前進行了加操做,是安全的;後者是在erase執行後才進行加操做,而此時iter已經被刪除(當前的迭代器已經失效了),對一個已經失效的迭代器進行加操做,行爲是不可預期的,這種寫法勢必會致使 map操做的失敗並引發進程的異常。string