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

3 篇文章 0 订阅

需求是这样的

map对象是 std::map<int, std::vector>

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

int GroupByCache::erase_by_tablename(vector<string> table_name)
{
    thr_scoped_spinlock _(splock);
    vector<int> 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 groupby\n");
}

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

然而当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<string> table_name)
{
    thr_scoped_spinlock _(splock);
    vector<int> 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 groupby\n");
}

题外话

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

准备增加一个map<table_name, cache*>用于删除cache。

复杂度来到Nlog2N

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值