STL的map表里有一個erase方法用來從一個map中刪除掉指令的節(jié)點
eg:
map<string,string> mapTest;
typedef map<string,string>::iterator ITER;
ITER iter=mapTest.find(key);
mapTest.erase(iter);
像上面這樣只是刪除單個節(jié)點,map的形為不會出現任務問題,
但是當在一個循環(huán)里用的時候,往往會被誤用,那是因為使用者沒有正確理解iterator的概念.
像下面這樣的一個例子就是錯誤的寫法,
eg.
for(ITER iter=mapTest.begin();iter!=mapTest.end();++iter)
{
cout<<iter->first<<":"<<iter->second<<endl;
mapTest.erase(iter);
}
這是一種錯誤的寫法,會導致程序行為不可知.究其原因是map 是關聯容器,對于關聯容器來說,如果某一個元素已經被刪除,那么其對應的迭代器就失效了,不應該再被使用;否則會導致程序無定義的行為。
可以用以下方法解決這問題:
正確的寫法
1.使用刪除之前的迭代器定位下一個元素。STL建議的使用方式
for(ITER iter=mapTest.begin();iter!=mapTest.end();)
{
cout<<iter->first<<":"<<iter->second<<endl;
mapTest.erase(iter++);
}
2. erase() 成員函數返回下一個元素的迭代器
for(ITER iter=mapTest.begin();iter!=mapTest.end();)
{
cout<<iter->first<<":"<<iter->second<<endl;
iter=mapTest.erase(iter);
}
注意:
map的earse應注意:
map這種容器的下邊訪問和Vector等容器的下標訪問有本質的區(qū)別。
對于Vector容器,用aVector[i]訪問第i個元素時,如果元素不存在,容器不會增加元素,
而對于map,用aMap[key]
訪問鍵key對應的對象時,如果該鍵對應的對象存在,則返回該對象(這和Vector一樣),但是,當鍵值為key的元素不存在時,容器會自動的增加一個 pair,鍵為key,而值則為一個容器定義時指定的類型并默認初始化(即,如果該類型為基本類型,則初始化為0,比如本例中,aMap[1]的使用會產 生一個pair,<1,NULL>,若該類型為類類型,則調用默認構造函數初始化之)
顯然,本例中,aMap[1]為NULL,后面的erase()不會執(zhí)行,使得后面的
插入語句aMap.insert(1,new A())鍵值沖突
eg:如下代碼會導致錯誤
#include <iostream>
#include <map>
using namespace std;
struct A
{
A(int i)
{
x=i;
}
int x;
};
int main()
{
map<int,A*> amap;
if ( amap[1] != NULL )
amap.erase(1);
amap.insert(make_pair(1,new A(1)));
amap.insert(make_pair(2,new A(2)));
amap.insert(make_pair(3,new A(3)));
return 0;
}