栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

C++ std::map用迭代器遍历删除遇到的坑

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

C++ std::map用迭代器遍历删除遇到的坑

需求是这样的

map对象是 std::map

函数erase_by_name(std::string name),需要用迭代器it遍历map,从it->second中找到name后删除it,直到遍历完成。

int GroupByCache::erase_by_tablename(vector table_name)
{
    thr_scoped_spinlock _(splock);
    vector delete_index;
    for (size_t k = 0; k < table_name.size(); k++)
    {
        for (auto it = caches_map.begin(); it != caches_map.end(); ++it)
        {
            auto &vec = it->second->table_name_vec;
            if (std::find(vec.begin(), vec.end(), table_name[k]) != vec.end())
            {
                it = caches_map.erase(it);
            }
        }
    }
    printf("erase groupbyn");
}

 表面上看没什么问题,迭代器也在删除后做了赋值,感觉自己避开了坑,很开心。

然而当map只有一个元素的时候,在erase(it)后,

it的值是map.begin(),此时map.begin()==map.end()。

for结束一次循环,++it,那么it = map.begin() + 1,不再等于map.end(),

循环继续,并且不会再停下来。

在这个项目中,锁也没有释放,就会让后面的线程全部堵在自旋锁上,cpu占用 += 100%。

出现这个问题的另一个 原因是,map没有重载大于小于比较符,只有不等于。

知道问题后,解决方法也不难。

把 ++it 作为 it 的 else 即可。

int GroupByCache::erase_by_tablename(vector table_name)
{
    thr_scoped_spinlock _(splock);
    vector delete_index;
    for (size_t k = 0; k < table_name.size(); k++)
    {
        for (auto it = caches_map.begin(); it != caches_map.end(); )
        {
            auto &vec = it->second->table_name_vec;
            if (std::find(vec.begin(), vec.end(), table_name[k]) != vec.end())
            {
                it = caches_map.erase(it);
            }
            else ++it;
        }
    }
    printf("erase groupbyn");
}

题外话

可能会有人吐槽这种遍历复杂度太高N^3。

准备增加一个map用于删除cache。

复杂度来到Nlog2N

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1009255.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号