C++ STL 遍历 map 的时候如何删除其中的 element

首先看一段他人的一段文章:from: http://www.cnblogs.com/super119/archive/2011/10/11/2207541.html

我们通过map的erase(iterator it)方法删除元素的时候,如果此时erase处于遍历map的代码中,那么调用erase就需要小心一些。因为erase会导致输入参数iterator变的无效,从而影响后续的it++遍历map的逻辑。

简单做法是,先将要删除的it保存下来,然后将用于遍历map的it指向下一个位置,然后删除掉保存下来的it。如下面代码所示:

#include <map>
#include <string>
#include <iostream>
using namespace std;
int main()
{
map<string, string> map1;
map<string, string>::iterator mapit;
map<string, string>::iterator saveit;
map1["1"] = "2";
map1["2"] = "3";
map1["3"] = "4";
map1["4"] = "5";
cout << "Map size1: " << map1.size() << endl;
mapit = map1.begin();
while (mapit != map1.end()) 
{
cout << "Element key: " << mapit->first << ", value: " << mapit->second << endl;
if (mapit->first == "2") 
{
saveit = mapit;
mapit++;
map1.erase(saveit);
continue;
}
mapit++;
}	
cout << "Map size2: " << map1.size() << endl;
return 0;
}

需要注意的是,这里windows的STL(windows C++编译器带的STL)和linux上的STL(gcc的STL)实现不同。

windows的STL中,map的erase方法会返回一个iterator,这个iterator指向的是当前被删除的iterator后面的iterator,所以这样的话,只需要将用于循环的iterator赋成erase函数的返回值就可以了。参考上面代码,就是这样:

mapit = map1.erase(mapit);然后continue就可以。

但是Linux下这样写代码是无法通过编译的。

--------------------------------------------------------------------------------------------------------------------------------------

另外,我将上面代码中的while()改了下:

while (mapit != map1.end()) 
{
cout << "Element key: " << mapit->first << ", value: " << mapit->second << endl;
if (mapit->first == "2") 
{
saveit = mapit;
//mapit++;
map1.erase(saveit);
//continue;
}
mapit++;
}	


经过修改之后,在vc6中调试时发现程序运行到mapit++;时就遇到了异常,不调试程序是可以正常运行下去的,但结果却不正确,而且与linux下的运行结果也不同。

上述修改后的代码在vc6中运行结果为:

Map size1: 4
Element key: 1, value: 2
Element key: 2, value: 3
Press any key to continue


在linux中运行结果为:

[zcm@t #19]$./t
Map size1: 4
Element key: 1, value: 2
Element key: 2, value: 3
Element key: 1, value: 2
Element key: 3, value: 4
Element key: 4, value: 5
Map size2: 3

 

注意到区别了吗?再仔细看看!

 ===========================================================

下面是一个更简单(看delValue函数)的写法,完整程序如下:

/*
map遍历并删除符合条件的元素
*/
#ifndef WIN32
#include <string.h>		// Linux下得用此文件(strcmp要用到)
#else
#include <string>
#endif
#include <iostream>
#include <map>
using namespace std;
void display(map<string, string>& m)
{
for(map<string, string>::iterator it = m.begin(); it != m.end(); it++)
{
cout << "(" << it->first << ", " << it->second << ")" << endl;
}
cout << endl;
}
// 删除m中值为value的元素, 返回被删除元素的个数
int delValue(map<string, string>& m, const char* value)
{
int delCnt = 0;		// 统计被删除元素个数
map<string, string>::iterator it = m.begin();
while(it != m.end())
{
if(strcmp(it->second.c_str(), value) == 0)
{
#if 1				// 此写法在windows和Linux上都OK(运行结果也正确)
m.erase(it++);
#else				// 此写法在windows上运行程序无法正常退出,应该是卡在当前while出不来了
m.erase(it);
it++;
#endif
delCnt++;
}
else
it++;
}
return delCnt;
}
int main()
{
map<string, string> map1;
map1["1"] = "3";
map1["2"] = "3";
map1["3"] = "4";
map1["4"] = "3";
cout << "Before delete, Map size = " << map1.size() << endl;
display(map1);
#if 1
int c = delValue(map1, "3");
cout << "delCnt = " << c << endl;
#else
map<string, string>::iterator mapit;
map<string, string>::iterator saveit;
mapit = map1.begin();
while (mapit != map1.end()) 
{
cout << "Element key: " << mapit->first << ", value: " << mapit->second << endl;
if (mapit->first == "2") 
{
saveit = mapit;
mapit++;
map1.erase(saveit);
continue;
}
mapit++;
}
#endif
cout << "After delete, Map size = " << map1.size() << endl;
display(map1);
return 0;
}


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/407391.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

React开发(111):写注释的方法

放上去会显示(method) Template.getDictionary(): void

数据库范式(1NF 2NF 3NF BCNF)详解

数据库的设计范式是数据库设计所需要满足的规范&#xff0c;满足这些规范的数据库是简洁的、结构明晰的&#xff0c;同时&#xff0c;不会发生插入&#xff08;insert&#xff09;、删除&#xff08;delete&#xff09;和更新&#xff08;update&#xff09;操作异常。反之则是…

小程序页面跳转的几个方法和区别

目前小程序的几个页面跳转方式的主要区别就两点&#xff1a; 1.是否可以返回上一个页面2.目标页面是否是tabBar 两个通用属性 1.限制&#xff1a;目前页面路径最多只能十层。2.分类&#xff1a;wx.navigateTo 和 wx.redirectTo不允许跳转到 tabbar 页面&#xff0c;只能用 w…

再学 GDI+[98]: TGPImage(18) - 获取 GDI+ 图像格式对应的 GUID

和在 Net 中不同的是, 在具体指定图像格式时, 这里常常需要的不是格式名称, 而是格式的 GUID;知道了格式名称, 用 GetEncoderClsid 函数可以获取格式的 GUID;GetEncoderClsid 函数来自 GDIPUTIL 单元, 本例并没有用到前面一直不可或缺的 GDIPOBJ、GDIPAPI 单元.如果要获取 imag…

STL::map默认会按照.first的字母顺序排列

看个代码&#xff1a; // map默认会按照.first的字母顺序排列#include <map>#include <string>#include <iostream>using namespace std;int main(){map<string, string> map1;map<string, string>::iterator mapit;map<string, string>:…

JS之连接数组方法concat

作用&#xff1a;用于连接两个或多个数组&#xff0c;该方法不会改变现有的数组&#xff0c;而仅仅会返回被连接数组的一个副本 语法&#xff1a;arrayObject.concat(arrayX,arrayX,……,arrayX) 参数&#xff1a;arrayX&#xff0c;必需。该参数可以是具体的值&#xff0c;也…

configure: error: Curl library not foun

yum -y install curl-devel 转载于:https://www.cnblogs.com/lehao/p/3903189.html

微信小程序:生命周期

下面从三个方面来介绍小程序的生命周期&#xff1a; &#xff08;1&#xff09;应用生命周期 &#xff08;2&#xff09;页面生命周期 &#xff08;3&#xff09;应用及页面生命周期的触发顺序 1.应用生命周期 App() 必须在 app.js 中调用&#xff0c;必须调用且只能调用一次…

在.NET3.5平台上使用LinQ to SQL + NBear 创建三层WEB应用

看了《一步一步学Linq to sql》和《在.NET 3.5 平台上使用LINQ to SQL创建三层/多层Web应用系统》 这两个系列文章后,因为一直使用NBear,所以试着综合了一下主要用NBear.IOC其它的NBear.data里的就没有会了,相应的使用LINQ来做数据处理. 之前一直使用NBear做些WEB应用主要感觉N…

递归修改子目录及文件的权限

背景&#xff1a;当我们的虚拟机和windows系统共享windows上的一个目录(记为&#xff1a;A)时&#xff0c;把该目录下的目录(记为B)移动(mv)到linux下的任意目录下&#xff0c;这个目录B及下面的子目录或文件的权限都是rwx(777)&#xff0c;这是他们在windows下的权限。因此用l…

JS之字符串连接方法join

作用&#xff1a;join() 方法用于把数组中的所有元素放入一个字符串&#xff0c;元素是通过指定的分隔符进行分隔的。&#xff08;作用和split正好相反&#xff09; 语法&#xff1a;arrayObject.join(separator) 参数&#xff1a;可选。指定要使用的分隔符。如果省略该参数&…

2.[Yii]创建与设置默认控制器及载入模板

1.创建控制器与访问 class IndexController extends Controller {//访问 index.php?rindex/index//r后面 其中第一个是控制器&#xff0c;第二个是方法&#xff0c;r就是路由route的缩写public function actionIndex(){$this->render("index");//载入模板文件} }…

程序根据手机机型设置自定义底部导航距离

需求: iponeX 以上机型,手机底部有弧度,自己写的导航栏会被遮住, 需要判断手机机型,做兼容设置. 解决: //app.js App({/*** 当小程序初始化完成时&#xff0c;会触发 onLaunch&#xff08;全局只触发一次&#xff09;*/onLaunch: function() {var that this;//获取手机型号…

张雨生《口是心非》

[hjp3]hjptypesong&player1&sonhttp://www.justin-rao.net/songs/[1997]%20ZhangYuSheng%20-%20KouShiXinFei%20-%2002%20-%20KouShiXinFei.mp3&autoplayno&captionfalse&lrc&autoreplay1&bgcolorFFFFFF&width200&height20[/hjp3] 转载于:…

JS之颠倒数组元素的reverse方法

作用&#xff1a;reverse() 方法用于颠倒数组中元素的顺序 语法&#xff1a;arrayObject.reverse() 注意&#xff1a;该方法会改变原来的数组&#xff0c;而不会创建新的数组 实例1&#xff1a;

图文:详解数据库Oracle 11g的基本安装

From: http://blog.csdn.net/wjcreator123/article/details/3243041 下面提供的是Oracle 11g的下载地址和基本安装过程&#xff08;仅作参考&#xff09; 第一步&#xff1a; oracle服务端下载: http://down.zdnet.com.cn/detail/9/82225.shtml 客户端: http://blog.csdn.net…

acid(数据库事务正确执行的四个基本要素的缩写)

ACID&#xff0c;指数据库事务正确执行的四个基本要素的缩写。包含&#xff1a;原子性&#xff08;Atomicity&#xff09;、一致性&#xff08;Consistency&#xff09;、隔离性&#xff08;Isolation&#xff09;、持久性&#xff08;Durability&#xff09;。一个支持事务&am…