I create a shared_ptr
for my test object, and put it in a std::map
, but its destructor is called before the program ends, and I don't know why.
Here is my test code:
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;
}
When I run the program, it waits at line while (true)
, but the output is:
create new one
in constructor
temp use count:1
in ~constructor
other use count:0
Before the program ends, I think my object should still be in memory, because the map holds a reference.
Another question: when I get other
from the map
, why is the use count 0? How to get the object back the right way?
BTW, if I comment out if(true){}
, the destructor is not called, but other
's use count is still 0.
operator []
of std::map
will insert element if not present in the map. std::map::insert()
will fail to insert anything if the element is already in the map. Thus, your insert()
call fails. You can verify it by checking the return value:
auto [iterator, wasInserted] = datas.insert(std::make_pair("key", temp));
std::cout << "insert call was " << (wasInserted ? "successful" : "unsuccessful") << '\n';
To update or create element if it doesn't exist, you can use operator[]
again:
if (!temp)
{
std::cout << "create new one" << std::endl;
temp = std::make_shared<Test>();
datas["key"] = temp;
}