有关(unordered_)map::erase的奇怪bug

背景

项目中使用unordered_map保存方便使用key快速索引对象
需要每次使用后根据key判断是否删除过期pair代码如下:

for(auto& pair : m)
{   
    if(!condition(pair.first))
    {
        m.erase(pair.first);
    }
}

捉虫

开始代码跑起来没问题,不久出现端倪偶发报错
打断点显示在if传入condition的pair为空抛出异常
仔细反思应该是erase发生清除后map长度变短
而for继续按照初始长度进行遍历直至越界

修复

既已定位到问题,尝试改写for逻辑

for (auto it = m.begin(); it != m.end(); )
{
    if(!condition(it->first)) 
    {
        m.erase(it++); 
    }
    else
    {
        ++it;
    }
}

优雅

自C++11后map::erase(itor)方法默认返回下一个itor可以用while改写

auto it = m.begin();
while(it != m.end())
{
    if(!condition(it->first))
    {
        pair = m.erase(it);
    }
    else
    {
        ++it;
    }
}

参考

c++ - Problem with std::map::iterator after calling erase() - Stack Overflow

上一篇:pseudo


下一篇:css定位 伪类 伪元素