遍历QMap引发异常处理

摘要:
在简介中,QMap以常规方式遍历。删除满足条件的元素时,出现“读取位置0xXXX时发生访问冲突”=TimerMap_T1_I-˃end();Iter++){if//如果键值对中的发送序列号小于或等于与tempNR对应的T1计时器,则重置计时器并移出键值对{killTimer;TimerMap_T1_I-˃erase;}}错误是删除元素后iter指针无效,返回到for语句,TimerMap_T1_I-˃end()在比较时出错。改进后,它遍历了QMap方法。QMap<int,int>::迭代器//遍历mapfor(iter=TimerMap_T1_I-˃begin();iter!

 

引言

用常规方法遍历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操作的失败并引起进程的异常。

总结
  1. QMap在进行 erase 之后,当前迭代器会失效
  2. ++操作符前置和后置的特性
参考

stl map高效遍历删除的方法 
在遍历中使用 iterator/reverse_iterator 进行 Erase 的用法

转自:https://blog.csdn.net/lm409/article/details/69257827

注意:

iterator QMap::end ()

返回一个stl风格迭代器指向map最后一个项目之后的虚构项目。

免责声明:文章转载自《遍历QMap引发异常处理》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇【opencv基础】OpenCV使用Viz模块3D可视化显示你真的了解三元运算符吗?下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

(转)Oracle存储过程

Oracle存储过程基本语法 存储过程   1 CREATE OR REPLACE PROCEDURE 存储过程名   2 IS   3 BEGIN   4 NULL;   5 END; 行1:   CREATE OR REPLACE PROCEDURE 是一个SQL语句通知Oracle数据库去创建一个叫做skeleton存储过程, 如果存在就覆盖它; 行...

【学习总结】《大话数据结构》- 第6章-树

【学习总结】《大话数据结构》- 总 第6章树-代码链接 启示: 树 目录 6.1 开场白 6.2 树的定义 6.3 树的抽象数据类型 6.4 树的存储结构 6.5 二叉树的定义 6.6 二叉树的性质 6.7 二叉树的存储结构 6.8 遍历二叉树 6.9 二叉树的建立 6.10 线索二叉树 6.11 树、森林与二叉树的转换 6.12 赫夫曼树及其应用 6...

python 异常处理、进程

目录: 异常处理 python进程 python并发之多进程 一、异常处理(try...except...) 1、程序中难免出现错误,而错误分成两种: a.语法错误: View Code b.逻辑错误(逻辑错误) View Code 2、异常定义:异常就是程序运行时发生错误的信号。 在python中,错误触发的异常,是以异常追踪信息、异常类型、异常值三...

对B+树,B树,红黑树的理解

 出处:https://www.jianshu.com/p/86a1fd2d7406 写在前面,好像不同的教材对b树,b-树的定义不一样。我就不纠结这个到底是叫b-树还是b-树了。 如图所示,区别有以下两点: B+树中只有叶子节点会带有指向记录的指针,而B树则所有节点都带有,在内部节点出现的索引项不会再出现在叶子节点中。 B+树中所有叶子节点都是通...

idea中的后缀补全

IDEA有个很牛逼的功能,那就是后缀补全(Postfix Completion),这个功能可以通过后缀来使用代码补全进行模板式地补全语句,如遍历循环语句(for、foreach)、使用 String.format() 包裹一个字符串、使用类型转化包裹一个表达式、根据判(非)空或者其它判别语句生成 if 语句、用instanceOf生成分支判断语句等。 听起...

.Net中的异常处理:高级异常

这种处理的有效性主要取决于所选择的语言和平台,因此,详细了解它们的正确用法和行为非常重要,这样我们的用户和其他开发人员在诊断代码中的问题时免受痛苦。在本文中,我们将了解C和.NET在错误处理方面的作用。 词汇表CLR:公共语言运行时的缩写,是.NET运行时,它负责执行用所有.NET语言编译的应用程序。除了虚拟机和实时编译器之外,它还具有额外的职责,如内存管...