擦除元素后std :: map :: iterator的有效性

时间:2013-09-09 12:54:00

标签: c++ dictionary iterator std stdmap

我已经编写了一个代码来解决以下问题:我们有map<double,double>个(相对)大量的项目。我们想合并相邻的项目,以减少地图的大小,保持一定的“损失因子”尽可能低。

为此,我首先填充一个包含相邻迭代器和相关损耗因子的列表(假设每个列表元素具有以下类型:

struct myPair {
    map<double,double>::iterator curr, next;
    double loss;
    myPair(map<double,double>::iterator c, map<double,double>::iterator n, 
        double l):  curr(c), next(n), loss(l) {}
};

)。这样做如下:

for (map<double,double>::iterator it1 = myMap.begin(); it1 != --(myMap.end()); 
    it1++) {
    map<double,double>::iterator it2 = it1; it2++;
    double l = computeLoss(it1,it2); 
    List.push(myPair(it1,it2,l));
}

然后,我找到对应于最低损失因子的列表元素,erase来自mapinsert的相应元素一个新元素(合并curr的结果和next中的map}。由于这也会更改next之后或curr之后的元素对应的列表元素,因此我会更新相应的条目以及相关的损失因子。

(我没有深入了解如何有效地实现上述内容,但基本上我将双链表与堆结合起来。)

虽然erase操作不应该使程序的某些特定输入实例的剩余迭代器无效,但是在我尝试从{{1}擦除元素时,我得到了double free or corruption错误。 }}

我尝试跟踪此情况,当两个地图元素的mapfirst条目非常接近时(更准确地说second的{​​{1}}时,似乎会发生这种情况。 }}和first非常接近)。

奇怪的是,我在填充列表的同时放置curr以确保所有条目nextassert在循环中不同且curr删除元素。第二个失败了!

如果有人能帮助我,我将不胜感激。

P.S。对不起,我很抱歉,但我希望尽可能保持细节。

更新:这是我从地图中删除元素的(非常简化的版本):

next

2 个答案:

答案 0 :(得分:0)

容器修改后myPair中存储的迭代器保持无效。你应该避免这种技术。可能当您查看头文件时,您会找到一些适合您的任务的草稿?

答案 1 :(得分:0)

正如其他人已经提到的,事实证明使用double作为map的关键是有问题的。特别是在计算值时。

因此,我的解决方案是使用std::multimap而不是map(然后在填充地图后将元素与相同的键合并)。有了这个,例如即使a非常接近t.currt.next或任何其他元素的键,确保insert操作创建一个新的元素, iterator中的现有list不会指向该内容。