Search code examples
c++pointerssmart-pointers

Erasing container that holds a shared pointer also deletes the object that's being pointed to?


For example, using raw pointer:

Object *obPointer = new Object(); //dynamically allocating memory, meaning we have to delete it, ourselves, later

std::unordered_map<std::string, Objects*> objContainer; //container that holds a string key and a pointer to an object type.

objContainer.emplace("A", obPointer); // placing a string and a pointer to an object into the container. simple enough.

Now, if we erase that container, it won't free the memory we allocated, the "Object" type. So we have to manually delete it, right?

delete obPointer;


objContainer.erase("A"); 

If we hadn't deleted the obPointer, erasing the container wouldn't be enough - we would have a memory leak. Anyways, when it comes to shared pointers, I don't know if this works, since we don't call delete on them:

std::shared_ptr<Object> obPointer = std::make_shared<Object>(); //shared pointer

std::unordered_map<std::string, std::shared_ptr<Object>> container;

container.emplace("A", obPointer);

container.erase("A");

Did the smart pointer clean up after itself? Or it will only clean itself when it goes out of scope?


Solution

  • So, like Dave mentioned, I should've used an unique pointer. In my example, by erasing the container, it would not free up the memory allocated with shared_ptr. It would only delete the memory if it ran out of scope or references. Therefore, as Dave suggested, I used an unique_pointer to created the memory, then I "passed" it to the container using "std::move," which transfers ownership TO the container's pointer. Therefore, the memory will free as soon as I erase that container. Like so:

    //Container
    std::unordered_map<std::string, std::unique_ptr<Object>> //container;
    {//Scope just to demonstrate it works
     std::unique_ptr<Object> obPointer = std::make_unique<Object>(); //unique pointer
    
    /*Now we transfer the ownership to the container, making its life spam
    rely on the scope of the CONTAINER and the container itself*/
    container.emplace("A", std::move(obPointer)); //std::move very important
    
    }//only "obPointer" will die cuz of the scope, but it's null now. 
    // the actual object that we created didn't delete itself. It's in the container
    
    
    
    /*If we want to free up the memory, we should just erase the specific container
    or wait for it to be out of the scope.*/
     container.erase("A"); //pointer deleted and memory freed
    

    There you go. A way to "manually" delete a smart pointer. Very useful.