我把一个shared_ptr放到了一个map中,但是为什么这个对象在程序结束之前就被销毁了?

I put a shared_ptr into a map, but why is the object destructed before the program ends?

我为我的测试对象创建了一个shared_ptr,并把它放在了一个std::map中,但是它的析构函数在程序结束之前被调用了,我不知道为什么。

这是我的测试代码:

class Test
{
public:
    Test()
    {
        std::cout << "in constructor" << std::endl;
    }

    ~Test()
    {
        std::cout << "in ~constructor" << std::endl;
    }

    Test(Test&&)      = delete;
    Test(const Test&) = delete;
};
    
std::map<std::string, std::shared_ptr<Test>> datas;

int main(int argc, char* argv[])
{
    if (true)
    {
        auto temp = datas["key"];
        if (!temp)
        {
            std::cout << "create new one" << std::endl;
            temp = std::make_shared<Test>();
            datas.insert(std::make_pair("key", temp));
        }
        else
        {
            std::cout << "already exists,pass" << std::endl;
        }

        std::cout << "temp use count:" << temp.use_count() << std::endl;
    }

    auto other = datas["key"];

    std::cout << "other use count:" << other.use_count() << std::endl;

    while (true)
    {
        usleep(100);
    }

    std::cout << "program end" << std::endl;

    return 0;
}

当我运行程序时,它在第while (true)行等待,但输出是:

create new one
in constructor
temp use count:1
in ~constructor
other use count:0

在程序结束之前,我认为我的对象应该还在内存中,因为映射持有一个引用。

另一个问题:当我从 map 得到 other 时,为什么使用计数为 0?如何以正确的方式取回对象?

顺便说一句,如果我注释掉if(true){},析构函数不会被调用,但是other的使用次数仍然是0。

如果元素已经在地图中,

operator [] of std::map will insert element if not present in the map. std::map::insert() 将无法插入任何内容。因此,您的 insert() 呼叫失败。您可以通过检查 return 值来验证它:

auto [iterator, wasInserted] = datas.insert(std::make_pair("key", temp));
std::cout << "insert call was " << (wasInserted ? "successful" : "unsuccessful") << '\n';

要更新或创建不存在的元素,您可以再次使用operator[]

    if (!temp)
    {
        std::cout << "create new one" << std::endl;
        temp = std::make_shared<Test>();
        datas["key"] = temp;
    }