遍历QMap引发异常处理
引言
用常规方法遍历QMap,删除满足条件元素时出现“读取位置0xXXX时发生访问冲突”。查看“调用堆栈”指向QMap<int,int>::iterator::operator++()和QMapNode<int,int>::nextNode()
定位为删除iterator中元素引起iterator的遍历异常,特记录如下:
常规错误遍历QMap方法
QMap<int,int>::iterator iter; //遍历map
for (iter = TimerMap_T1_I->begin(); iter != TimerMap_T1_I->end(); iter++)
{
if (tempNR>=iter.key())//如果键值对中发送序号小于或等于该tempNR对应的T1计时器复位,并移出键值对
{
killTimer(iter.value());
TimerMap_T1_I->erase(iter);
}
}
错误在于: iter指针在元素被删除后失效了,回到for语句中与 TimerMap_T1_I->end()进行比较时发生错误
改进后遍历QMap方法
QMap<int,int>::iterator iter; //遍历map
for (iter = TimerMap_T1_I->begin(); iter != TimerMap_T1_I->end(); )
{
if (tempNR>=iter.key())//如果键值对中发送序号小于或等于该tempNR对应的T1计时器复位,并移出键值对
{
killTimer(iter.value());
TimerMap_T1_I->erase(iter++); //满足删除条件,删除当前结点,并指向下面一个结点
}
else
{
iter++;//条件不满足,指向下面一个结点
}
}
TimerMap_T1_I->erase(iter++) 中map中在删除iter的时候,先将iter做缓存为iter1,然后执行iter++使之指向下一个结点,再进入erase函数体中执行删除操作,删除时使用的iter其实是缓存下来的iter1(也就是当前iter(做了加操作之后的iter)所指向结点的上一个结点)。
这和TimerMap_T1_I->erase(iter); iter++;这种执行序列是不相同的。前者在erase执行前进行了加操作,在iter被删除(失效)前进行了加操作,是安全的;后者是在erase执行后才进行加操作,而此时iter已经被删除(当前的迭代器已经失效了),对一个已经失效的迭代器进行加操作,行为是不可预期的,这种写法势必会导致 map操作的失败并引起进程的异常。
总结
- QMap在进行 erase 之后,当前迭代器会失效
- ++操作符前置和后置的特性
参考
stl map高效遍历删除的方法
在遍历中使用 iterator/reverse_iterator 进行 Erase 的用法
转自:https://blog.csdn.net/lm409/article/details/69257827
注意:
iterator QMap::end ()
遍历QMap引发异常处理的更多相关文章
- HTML5本地存储localStorage、sessionStorage基本用法、遍历操作、异常处理等
HTML5 的本地存储 API 中的 localStorage 与 sessionStorage 在使用方法上是相同的,区别在于 sessionStorage 在关闭页面后即被清空,而 localSt ...
- C#基础知识 简单说明泛型的优点
有关泛型的优缺点在网上有很多篇文章,也足以说明问题,我就不去复制粘贴了(而且内容有些多),由于记性不太好,所以自己做个简单明了的总结. 泛型的优点主要有两个: "性能" " ...
- JDK源码分析(1)ArrayList
JDK版本 ArrayList简介 ArrayList 是一个数组队列,相当于 动态数组.与Java中的数组相比,它的容量能动态增长.它继承于AbstractList,实现了List, RandomA ...
- Java - 35 Java 实例
Java 实例 本章节我们将为大家介绍 Java 常用的实例,通过实例学习我们可以更快的掌握 Java 的应用. Java 环境设置实例 Java 实例 – 如何编译一个Java 文件? Java 实 ...
- Python os.md
os 便携式访问操作系统的特定功能.os模块提供了对特定平台模块(如posix, nt, mac)的封装, 函数提供的api在很多平台上都可以相同使用, 所以使用os模块会变得很方便. 但不是所有函数 ...
- wk_06.md
IO与文件操作 文件内建函数open 内建函数open提供了初始化输入/输出(I/O)操作的通用接口.open()内建函数成功打开文件后会返回一个文件对象.open函数的语法如下: open(file ...
- js的同步异步
由于js没有多线程,所以处理多任务的时候,可以用异步回调来解决.js中setTimeout.setInterval.ajax(jq中可以选择同步或异步)均会开启异步.遇到异步模块,会将其推入值任务队列 ...
- Java-Runoob-高级教程:Java 实例
ylbtech-Java-Runoob-高级教程:Java 实例 1.返回顶部 1. Java 实例 本章节我们将为大家介绍 Java 常用的实例,通过实例学习我们可以更快的掌握 Java 的应用. ...
- Java 实例
Java 实例 本章节我们将为大家介绍 Java 常用的实例,通过实例学习我们可以更快的掌握 Java 的应用. Java 环境设置实例 Java 实例 – 如何编译一个Java 文件? Java 实 ...
随机推荐
- Unity GPU Instancing的使用尝试
似乎是在Unity5.4中开始支持GPU Instacing,但如果要比较好的使用推荐用unity5.6版本,因为这几个版本一直在改. 这里测试也是使用unity5.6.2进行测试 在5.6的版本里, ...
- 03.反射--01【反射机制】【反射的应用场景】【Tomcat服务器】
https://blog.csdn.net/benjaminzhang666/article/details/9408611 https://blog.csdn.net/benjaminzhang66 ...
- NET二进制图片存储与读取的常见方法,iTextSharp添加图片生成PDF文件
public void iTextSharpCreatPDF() { string pdfpath = System.Web.HttpContext.Current.Server.MapPath(&q ...
- elastic search internal
Realtime Search with Lucene http://2010.berlinbuzzwords.de/sites/2010.berlinbuzzwords.de/files/busch ...
- (原创)c++11改进我们的模式之改进观察者模式
和单例模式面临的是同样的问题,主题更新的接口难以统一,很难做出一个通用的观察者模式,还是用到可变模板参数解决这个问题,其次还用到了右值引用,避免多余的内存移动.c++11版本的观察者模式支持注册的观察 ...
- debian8.5安装sublime text3
在官网www.sublimetext.com下载安装包 我这里用的是Ubuntu 64 bit版. 下载后使用su命令切换到root账户. 执行安装命令 dpkg -i sublime-text*.d ...
- 查准与召回(Precision & Recall)
Precision & Recall 先看下面这张图来理解了,后面再具体分析.下面用P代表Precision,R代表Recall 通俗的讲,Precision 就是检索出来的条目中(比如网页) ...
- Zend Studio 12 windows 无限期试用
安装: 1.下载最新版本Zend Studio:http://downloads.zend.com/studio-eclipse/12.0.0/ZendStudio-12.0.0-win32.win3 ...
- Tips for Navigating Large Game Code Bases
http://solid-angle.blogspot.com/2015/08/tips-for-navigating-large-game-code.html
- c语言中条件编译相关的预编译指令
一. 内容概述 本文主要介绍c语言中条件编译相关的预编译指令,包括#define.#undef.#ifdef.#ifndef.#if.#elif.#else.#endif.defined. 二.条件编 ...