You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

将shared_ptr存入std::map后对象提前析构、引用计数为0如何解决?

问题根因

你遇到的所有现象核心是两个点:

  1. std::map的operator[]在key不存在时会自动隐式插入一个默认构造的对应值
  2. std::map::insert操作在key已经存在的情况下会直接插入失败,不会覆盖原有值

执行流程拆解

你的代码实际执行顺序如下:

  1. 执行auto temp = datas["key"]:此时map中不存在key,operator[]自动往map插入一个空的std::shared_ptr<Test>,然后将这个空智能指针拷贝给temp,此时temp是空值,引用计数为0
  2. 判定temp为空,调用std::make_shared<Test>创建对象,赋值给temp,此时temp的引用计数为1
  3. 执行datas.insert(std::make_pair("key", temp)):因为key已经被第一步的operator[]插入到map中,insert直接失败,你创建的智能指针并没有被存入map
  4. if代码块结束,局部变量temp被销毁,它持有的智能指针引用计数从1降到0,对应的Test对象被析构
  5. 后面执行auto other = datas["key"]:拿到的是第一步自动插入的空智能指针,空智能指针的use_count默认就是0,所以输出0

你补充测试中注释掉if块的现象也符合这个逻辑:直接调用datas["key"]只会自动插入空智能指针,没有创建Test对象自然不会调用析构,空指针的use_count自然是0。


正确的实现方式

这里给两种常用的写法,都可以避免你遇到的问题:

写法1:直接修改operator[]返回的引用

避免拷贝operator[]的返回值,直接用引用接收,修改引用就等价于修改map中存储的值:

if (true)
{
    // 用引用接收,不要做拷贝
    auto& temp = datas["key"];
    if (!temp)
    {
        std::cout << "create new one" << std::endl;
        // 直接给map中的元素赋值
        temp = std::make_shared<Test>();
    }
    else
    {
        std::cout << "already exists,pass" << std::endl;
    }
    std::cout << "temp use count:" << temp.use_count() << std::endl;
}

写法2:用find先判断,避免隐式插入

如果不希望key不存在时自动插入空值,可以先用find判断是否存在,不存在再插入:

if (true)
{
    auto it = datas.find("key");
    if (it == datas.end())
    {
        std::cout << "create new one" << std::endl;
        auto temp = std::make_shared<Test>();
        datas.emplace("key", temp);
        std::cout << "temp use count:" << temp.use_count() << std::endl;
    }
    else
    {
        std::cout << "already exists,pass" << std::endl;
        std::cout << "temp use count:" << it->second.use_count() << std::endl;
    }
}

注意事项

  • 仅当你确定需要在key不存在时插入默认值的时候,才使用operator[],单纯查询优先用find
  • std::map的插入接口区别要注意:insert仅key不存在时插入,insert_or_assign会覆盖已有key的值,C++17新增的try_emplace在key不存在时才构造元素,性能比insert更高

内容的提问来源于stack exchange,提问作者宝蓝娃娃

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 00:57:03