Search code examples
c++pointersc++11raii

Raw pointer inside std::make_shared


I readily admit to still learning the finer notes of pointers in C/C++ and how they work but after doing some research, I just don't feel comfortable with the code below.

std::shared_ptr<CDKSCREEN> cdkScreen;
cdkScreen = std::make_shared<CDKSCREEN>(*initCDKScreen(newWin.get()));

Does the usage of raw pointers inside a std::shared_ptr nullify any of the benefits you get from using smart pointers? Or is it just all the same either way? Thank you and I appreciate any answers to this post.


EDIT: I did not realize the full purpose of the reset() function but thank you to all who pointed this out to me. It seems I can also pass a custom destructor to std::shared_ptr as well, like below:

std::shared_ptr<CDKSCREEN> cdkScreen(initCDKScreen(newWin.get()), destroyCDKScreen);

Solution

  • I believe your example actually has a memory leak. Let's break it down:

    CDKSCREEN* screen = initCDKScreen(newWin.get());
    CDKSCREEN& screenRef = *screen;
    
    // auto screenSharedPtr = std::make_shared<CDKSCREEN>(screenRef);
    // this is basically:
    
    CDKSCREEN* screen2 = new CDKSCREEN(screenRef);
    shared_ptr<CDKSCREEN> screenSharedPtr (screen2);
    

    As you can see, a copy is being made, but the original pointer isn't deleted. Oops.


    If initCDKScreen returns something that has to just be deleted, then in this case I'd avoid the copy/move ctor and just .reset() the smart pointer to it:

    std::shared_ptr<CDKSCREEN> cdkScreen;
    cdkScreen.reset(initCDKScreen(newWin.get()));
    

    Actually, since it even has a constructor overload for that, go ahead and

    std::shared_ptr<CDKSCREEN> cdkScreen { initCDKScreen(newWin.get()) };
    

    If a custom destruction facility is needed, you can pass it as a 2nd parameter to the pointer. It makes perfect sense and smart pointer classes were designed for that.