C++ std::map::erase用法及其陷阱
1.引入:
STL的map中有一个erase方法用来从一个map中删除制定的节点
eg:
map<string,string> mapTest;
typedef map<string,string>::iterator ITER;
ITER iter=mapTest.find(key);
mapTest.erase(iter);
像上面这种删除单个节点,map的行为不会出现问题,但是当在一个循环里用的时候,往往会被误用。
2.陷阱
eg:
for(ITER iter=mapTest.begin();iter!=mapTest.end();++iter)
{
cout<<iter->first<<":"<<iter->second<<endl;
mapTest.erase(iter);
}
这是一种错误的写法,会导致程序行为不可知,原因是map是关联容器,对于关联容器来说,如果一个元素已经被删除,那么其对应的迭代器就失效了,不应该再被使用,负责会导致程序无定义的行为。
3.正确用法
正确用法一:(C++11可以,C++98不行)
erase() 成员函数返回下一个元素的迭代器
std::map<std::string, std::string >::iterator it = mapTest.begin();
while(it != mapTest.end())
{
if(TestVal(it->second))
{
it = mapTest.erase(it);
}
else
it++;
}
正确用法二:
使用删除之前的迭代器定位下一个元素。STL建议的使用方式
for(ITER iter=mapTest.begin();iter!=mapTest.end();) //注意此处不能再写iter++
{
cout<<iter->first<<":"<<iter->second<<endl;
mapTest.erase(iter++);
}
在这种用法中,该方法中利用了后++的特点,这个时候执行mapTest.erase(it++);这条语句分为三个过程
1、先把it的值赋值给一个临时变量做为传递给erase的参数变量
2、因为参数处理优先于函数调用,所以接下来执行了it++操作,也就是it现在已经指向了下一个地址。
3、再调用erase函数,释放掉第一步中保存的要删除的it的值的临时变量所指的位置。
4.例子
case1: ✅
#include<map>
#include<iostream>
int main()
{
std::map<int, int> map_a;
std::map<int, int>::iterator it; for (int i = ; i != ; i++) {
map_a.insert(std::map<int, int>::value_type(i, i));
} for (it = map_a.begin(); it != map_a.end(); it++){
std::cout<< it->first <<std::endl;
// map_a.erase(it->first);
} return ;
}
结果:
case2:❌
#include<map>
#include<iostream>
int main()
{
std::map<int, int> map_a;
std::map<int, int>::iterator it; for (int i = ; i != ; i++) {
map_a.insert(std::map<int, int>::value_type(i, i));
} for (it = map_a.begin(); it != map_a.end(); it++){
std::cout<< it->first <<std::endl;
map_a.erase(it->first);
} return ;
}
结果:
当将map大小加到1000000的时候,出core
5.导致程序行为不可知的原因
5.1 list和vector的erase方法都返回一个iterator,指向被删除元素的下一个元素,唯独map,set,multimap,multiset这4个竟然返回void.
不过在C++11中已经改正过来了,都返回一个iterator

原因:迭代器++的操作是在操作它保存的节点指针,所以当这个节点被删除的时候,改节点所指向的指针是无法确定的,也就是可能还是以前的数据,也可能是已经其他毫不相关的数据了,这样的行为被叫做未定义的行为,不一定会core.
C++ std::map::erase用法及其陷阱的更多相关文章
- std::map用法
STL是标准C++系统的一组模板类,使用STL模板类最大的好处就是在各种C++编译器上都通用. 在STL模板类中,用于线性数据存储管理的类主要有vector, list, map 等等.本文主要 ...
- map::erase陷阱
map::erase函数在不同版本stl中的差异 1. C++98和C++11标准 http://www.cplusplus.com/reference/map/map/erase/ 2. pj st ...
- [转] C++ STL中map.erase(it++)用法原理解析
总结一下map::erase的正确用法. 首先看一下在循环中使用vector::erase时我习惯的用法: for(vector<int>::iterator it = vecInt.be ...
- C++ std::map用法简介
#include "map" //引入头文件 初始化: std::map <int, std::string> _map1; //初始化 //c++11中引入的,可以直 ...
- c++map的用法 分类: POJ 2015-06-19 18:36 11人阅读 评论(0) 收藏
c++map的用法 分类: 资料 2012-11-14 21:26 10573人阅读 评论(0) 收藏 举报 最全的c++map的用法 此文是复制来的0.0 1. map最基本的构造函数: map&l ...
- STL中map的用法
map是STL的一个关联容器,它提供一对一(其中第一个可以称为关键字,每个关键字只能在map中出现一次,第二个可能称为该关键字的值)的数据处理能力,由于这个特性,它完成有可能在我们处理一对一数据的时候 ...
- C++11中map的用法
最全的c++map的用法 1. map最基本的构造函数:map<string ,int>mapstring; map<int,string >mapint;map<sri ...
- 关于map::erase的使用说明
C++ 中经常使用的容器类有vector,list,map.其中vector和list的erase都是返回迭代器,但是map就比较不一样. 当在循环体中使用map::erase语句时,为了能够在任何机 ...
- C语言 · C++中map的用法详解
转载自:http://blog.csdn.net/sunquana/article/details/12576729 一.定义 (1) map<string, int> Map ...
随机推荐
- DNX SDK版本 “dnx-clr-win-x86.1.0.0-beta5”无法安装
打开VS2015,出现 “DNX SDK版本 “dnx-clr-win-x86.1.0.0-beta5”无法安装,该解决方案将对此会话使用DNX SDK版本“dnx-clr-win-x86.1.0.0 ...
- 第1周 支路变量、元件、KCL和KVL
第1周的内容,介绍了: 电阻.独立源.受控元件等实体元器件, 电流.电压.功率等抽象名词, 端口.参考方向等分析时的概念工具, KCL.KVL两大分析定律, 解线性电路的普适方法----2B法. 引入 ...
- 10个使用Java最广泛的现实领域
10个使用Java最广泛的现实领域 如果你是一个初学者,刚刚开始学习Java,你可能会想Java有什么用呢?除了Minecraft貌似也看不到其他用Java写的游戏,像Adobe Acrobat和Mi ...
- linux中的chage命令
在LINUX系统上,密码时效是通过chage命令来管理的. 参数说明:-m 过多少天后可修改密码.为0时代表任何时候都可以更改密码.-M 过多少天后密码过期.-W 用户密码到期前,提前收到警告信息的天 ...
- VS2013开发 windows服务 挂到服务器上执行
这是百度经验的链接,本人主要参考的他.http://jingyan.baidu.com/article/cd4c2979e9330d756f6e6070.html 1 创建windows服务项目 2 ...
- SQLMAP 中$与#的区别
在sql配置中比如in(#rewr#) 与in ($rewr$) 在Ibatis中我们使用SqlMap进行Sql查询时需要引用参数,在参数引用中遇到的符号#和$之间的区分为,#可以进行与编译,进行类型 ...
- Visual Studio2008环境下查找C#中方法的“查看所有引用”
在Visual Studio开发环境下,想必F12我们都很熟悉了,有没有用过“查看所有引用”呢? 尤其是在一个解决方案中,包含了很多项目,彼此相互的调用是很常见的,例如三层架构, BLL调用DAL,D ...
- MVC中使用EF:排序,过滤,分页
原文链接:http://www.asp.net/mvc/tutorials/getting-started-with-ef-using-mvc/sorting-filtering-and-paging ...
- winrar命令行加压解密
加密的操作 Rar.exe a -P123 test1.rar test.txt 其中参数a表示添加文件或文件夹到压缩包中,-P参数表示是带密码的加密 Rar.exe e -P123 test1.ra ...
- 关于C++的递归调用(n的阶乘为例)
C++,是入门编程界的一门初期的语言.今天我们浅谈一下有关C++的递归调用. 在没有继承,多态,封装之前,C++几乎看成是C语言,除了一些简单的输出和头文件. 具体代码实现如下: #include&l ...