Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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);
like image 769
Phobos D'thorga Avatar asked Dec 18 '22 23:12

Phobos D'thorga


2 Answers

I think you want to save the pointer returned by initCDKScreen. In this case you don't have to use make_shared. You should pass the pointer to the constructor or shared_ptr::reset(...):

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

Since CDKSCREEN should be destroyed by destroyCDKScreen(CDKSCREEN *screen) and not with delete, you should write something like this:

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

or

std::shared_ptr<CDKSCREEN> cdkScreen;
cdkScreen.reset(initCDKScreen(newWin.get()), destroyCDKScreen);
like image 127
JojOatXGME Avatar answered Dec 30 '22 01:12

JojOatXGME


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.

like image 32
Bartek Banachewicz Avatar answered Dec 30 '22 03:12

Bartek Banachewicz