map的简介和使用
map是STL里重要容器之一。它的特性总结来讲就是:所有元素都会根据元素的键值key自动排序(也可根据自定义的仿函数进行自定义排序),其中的每个元素都是<key, value>的键值对,map中不允许有键值相同的元素,因此map中元素的键值key不能修改,但是可以通过key修改与其对应的value。如果一定要修改与value对应的键值key,可将已存在的key删除掉,然后重新插入。
map<string, int> m; // 定义一个空的map m,键是string类型的,值是int类型的
m["hello"] = 2; // 将key为"hello", value为2的键值对(key-value)存入map中
// 用迭代器器遍历,输出map中所有的元素,键用it->first获取,值用it->second获取
for (auto it = m.begin(); it != m.end(); it++) {
cout << it->first << " " << it->second << endl;
}
其他使用方法不再举例说明。
std::map::erase的用法及常见错误
STL的map表里有一个erase方法,用来从一个map中删除掉指定的节点。
先看基本的使用方法:
map<string,string> mapTest;
map<string,string>::iterator pit = mapTest.find(key);
if(pit != mapTest.end())
{
mapTest.erase(iter);
}
像上面这样只是删除单个节点,map的erase操作不会导致问题,
但是当在一个循环里使用erase的时候,往往会导致错误。
常见的错误例子:
map<int,string> mapTest;
map<int, string>::iterator itor ;
for (itor = mapTest.begin(); itor != mapTest.end(); ++itor)
{
if (itor->second == "abc")
{
mapTest.erase(itor) ; //错误的写法
}
}
原因分析:
map是关联式容器,调用erase后,当前迭代器已经失效,然后对itor进行操作,会发生传说中的“未定义的行为”!
在循环中正确使用map::erase的方法是什么呢?如下:
map<int,string> mapTest;
map<int, string>::iterator itor ;
for (itor = mapTest.begin(); itor != mapTest.end();)
{
if (itor->second == "abc")
{
mapTest.erase(itor++) ;
}
}
或者使用while循环
map<int,string> mapTest;
map<int, string>::iterator itor ;
while (itor != mapTest.end();)
{
if (itor->second == "abc")
{
m.erase(itor++) ;
}
}
该解决方法较详细的一种解释为:
http://blog.csdn.net/lmh12506/article/details/9167653
该方法中利用了后缀++的特点,这个时候执行mapInt.erase(it++);这条语句分为三个过程
1、先把it的值赋值给一个临时变量做为传递给erase的参数变量
2、因为参数处理优先于函数调用,所以接下来执行了it++操作,也就是it现在已经指向了下一个地址。
3、再调用erase函数,释放掉第一步中保存的要删除的it的值的临时变量所指的位置。
值得一提的是,在最新的C++11标准中,已经新增了一个map::erase函数执行后会返回下一个元素的iterator。也可以使用erase的返回值使得迭代器获得下一个有效的地址。




