关于错误map/set iterator not incrementable
来源:互联网 发布:淘宝删除差评步骤 编辑:程序博客网 时间:2024/05/17 23:58
今天Debug代码时,碰到一个关于迭代器的崩溃错误(仅限Debug模式,release会被容错):map/set iterator not incrementable,相关代码如下(仅演示思路代码):
//pretypedeftypedef std::multimap<int, int>::iterator multimapIterator;typedef std::pair<multimapIterator, multimapIterator> milmapIteratorPair;std::set<int> testSet;std::multimap<int, int> muiMap;//muiMap will be sorted automatically: { (1, 1), (1, 2), (2, 3), (3, 4) }//even through with chaos insert ordermuiMap.insert(std::pair<int, int>(1, 1));muiMap.insert(std::pair<int, int>(2, 3));muiMap.insert(std::pair<int, int>(1, 2));muiMap.insert(std::pair<int, int>(2, 4));for (multimapIterator pMultimapIt = muiMap.begin(); pMultimapIt != muiMap.end(); ++pMultimapIt){ unsigned int iCount = muiMap.count(pMultimapIt->first); if (2 <= iCount) { milmapIteratorPair resultPair = muiMap.equal_range(pMultimapIt->first); multimapIterator it = resultPair.first; while (it != resultPair.second) { testSet.insert(it->second); ++it; } //erase all elements with key pMultimapIt->first, return erased count muiMap.erase(pMultimapIt->first); pMultimapIt = muiMap.begin(); }}
代码初看之下没有问题,功能也都正常:将muiMap中key值出现次数等于或者多于两次的元素的值(value)存到testSet中,并从muiMap将这些元素删除。
但是,实际上该段代码存在两个问题:
1. 特定情况下会访问非法的iterator。
2. 遍历时,会有元素遗漏,尽管对功能没有影响。
我们一个一个来看。
1. 特定情况下会访问非法的iterator
这个问题多少跟for循环的执行顺序有关系,对于如下for循环:
for(A.initialization; B.condition; C.increment){ D...}
其执行顺序为:
A->B->D->C->B->D->C->B->D…C->B->D,直到条件不满足。
而当muiMap中所有元素的出现次数都满足条件时,对于如下代码:
for (multimapIterator pMultimapIt = muiMap.begin(); pMultimapIt != muiMap.end(); ++pMultimapIt){ ... pMultimapIt = muiMap.begin(); ...}
此时muiMap为空,muiMap.begin()等于muiMap.end(),这样pMultimapIt也就指向了一个非法的iterator,所以下次for循环时,++pMultimapIt是对非法iterator自增操作,会产生错误,该错误的一个修改方法是添加muiMap判空操作,如果为空直接跳出循环,但这样解决不了第二个问题。而且在下面会看到,解决第二个问题的同时,这个问题也可以解决掉。
2. 遍历时,会有元素遗漏,尽管对功能没有影响
例如,对于如下multimap: { (1, 1), (1, 2), (2, 3), (3, 4) }
第一次循环时,key值1出现次数满足条件,所以删除之:
muiMap.erase(pMultimapIt->first);
multimap为:{ (2, 3), (3, 4) },之后执行:
pMultimapIt = muiMap.begin();
此时pMultimapIt指向pair: (2, 3)。然后for循环判断未到达容器末尾,因此执行++pMultimapIt,此时pMultimapIt指向(3, 4),对于(2, 3)的遍历被跳过了,之所以在此例子中不影响功能,是因为如果被跳过的元素的key值出现次数多于两次,跳过一个仍然可以被删掉,这得益与multimap自动排序,key相同的元素会被排到一起。所以,在某些情况下,pMultimapIt不应该自增。修改后的代码如下:
...//no ++pMultimapIt anymorefor (multimapIterator pMultimapIt = muiMap.begin(); pMultimapIt != muiMap.end();) { unsigned int iCount = muiMap.count(pMultimapIt->first); if (2 <= iCount) { milmapIteratorPair resultPair = muiMap.equal_range(pMultimapIt->first); multimapIterator it = resultPair.first; while (it != resultPair.second) { testSet.insert(it->second); ++it; } muiMap.erase(pMultimapIt->first); pMultimapIt = muiMap.begin(); } else//increase pMultimapIt under conditions. { ++pMultimapIt; }}
经过如上修改,由于删掉元素后,pMultimapIt会指向新的元素,素以此时pMultimapIt不需要增加,只有未删掉元素(iCount > 2)时,需要继续遍历下一个元素,所以自增pMultimapIt。
对于问题1,如果muiMap被删为空,则此时pMultimapIt等于muiMap.end(),跳出for循环,问题1解决。
总结
对于容器的迭代器(iterator)操作,一定要小心迭代器非法的情况,此时对于迭代器的任何操作,都会导致显性或者隐性的问题,尤其很多容器在erase操作后,迭代器会失效,此时需要重新初始化迭代器,保证后对于它的操作合法。
- 关于错误map/set iterator not incrementable
- map/set iterator not incrementable
- map/set iterator not incrementable
- map/set iterator not incrementable set/map使用erase时注意事项!
- 如何避免“iterator not incrementable”错误
- 如何避免“iterator not incrementable”错误
- vector iterator not incrementable错误解决
- 关于vector iterator not incrementable的解决方案
- 错误map/set iterator not dereferencable
- vector iterator not incrementable
- list iterator not incrementable
- List Iterator Not Incrementable
- iterator not incrementable 解决方案
- string iterator not incrementable
- vector iterator not incrementable
- c++ list iterator not incrementable
- 迭代器失效 iterator not incrementable
- map/set iterator not dereferencable
- C函数与汇编函数之间参数及返回值传递方法
- java基础-面向对象-this关键字
- 嵌入式开发第64日(内核模块的依赖)
- leetcode-283-Move Zeros 顺序表
- linux多线程-互斥锁
- 关于错误map/set iterator not incrementable
- APICloud手机端网站直接制作手机APP
- 【Hadoop入门】Hadoop安装教程_单机/伪分布式配置_CentOS6.4/Hadoop2.6.0
- android 用canvas 绘制简单圆形时钟
- 基于OpenCV的膨胀和腐蚀
- ASP.NET MVC 微信JS-SDK认证
- MySQL索引原理及慢查询优化
- java中复制文本文件
- emWin 2天速成实例教程002_多个页面窗口切换