【问题标题】:Erase elements in a nested map擦除嵌套地图中的元素
【发布时间】:2016-02-22 08:14:49
【问题描述】:

我希望能够删除一个元素,但我不知道我缺少什么。程序崩溃。

void Movies::removePeliculaAlies(short unsigned year,string title){
    map<string,map<unsigned short, string> >::iterator itAlies=_mapaAlies.begin();
    while(itAlies!=_mapaAlies.end()){
        map<unsigned short,string>::iterator itInterior;
        itInterior=itAlies->second.find(year);
        if(itInterior!=itAlies->second.end()){
            if(title==itInterior->second){
                itAlies->second.erase(itInterior);->>>>>>>>>>>>>NOT WORKING WHY?
            }
            if(itAlies->second.size()==0) _mapaAlies.erase(itAlies->first);
        }
        itAlies++;
    }
}

【问题讨论】:

  • 你说,“为什么不工作?” ......但它有什么作用?它什么都不做吗?它会崩溃吗?
  • 是的程序崩溃了
  • 或许你可以试试调试它?

标签: c++ dictionary nested erase


【解决方案1】:

崩溃可能是由这段代码引起的:

    if(itAlies->second.size()==0) _mapaAlies.erase(itAlies->first);
}
itAlies++;

在这里您正在编辑_mapaAlies,然后您立即执行itAlies++;,即使迭代器itAlies 已被编辑无效。

相反,您可以尝试先进行增量,然后删除元素

    if(itAlies->second.size()==0){
        map<string,map<unsigned short, string> >::iterator oldIter = itAlies; // copy the iterator
        ++itAlies;                 // increment the iterator
        _mapaAlies.erase(oldIter); // erase the copy
        continue;                  // skip the incrementing in the end
    }
}
itAlies++;

一般来说,您应该在循环遍历容器的同时编辑容器,因为编辑可能会使迭代器无效并导致崩溃或更糟。

【讨论】:

  • erase 在被删除的元素之后返回一个迭代器,因此您无需创建副本即可,只需使用itAlies = _mapAlies.erase(itAlies);。您仍然需要 continue; 以避免第二次递增迭代器。
  • @ChrisDodd 根据cplusplus.com,新的迭代器在 C++11 之后返回,提问者可能没有使用。
【解决方案2】:

我在自己的代码中看到了类似的问题。我认为崩溃与您在地图中拥有地图这一事实没有任何关系。我认为问题更可能与您在迭代同一个地图时删除地图的元素有关。

我在自己的代码中解决了这个问题,如下所示:我迭代地图,如果我删除任何地图元素,我将引发一个布尔标志并中断我的迭代循环。在循环之后,如果该标志被提升,我将重新开始迭代并重复,直到不再需要擦除。这是我的代码:

void serve::reclaim_server_resources()
{
    dPrintf("()");

    bool erased = false;

    for (std::map<int, serve_client>::iterator iter = client_map.begin();
         iter != client_map.end(); ++iter) {
        if (!iter->second.check()) {
            dPrintf("erasing idle client...");
            client_map.erase(iter->first);
            /* stop the loop if we erased any targets */
            erased = true;
            break;
        }
    }

    /* if we erased a target, restart the above by re-calling this function recursively */
    if (erased)
        reclaim_server_resources();
}

如果我从循环中删除 break;,代码会崩溃,可能和你的一样。

这实际上只是针对您的问题的解决方法的建议。也许可能有更好的解决方案可用,但至少了解类似问题在其他类似情况下会如何表现应该会有所帮助。

如果你想自己尝试我的解决方法,你可能想把你的函数分成两个更小的函数,这样当你通过递归调用新函数重新开始迭代时,它可以重新开始内部映射的迭代,而不是重新启动整个外部地图。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-04-30
    • 1970-01-01
    • 1970-01-01
    • 2011-09-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多