views:

319

answers:

3

Much to my shame, I haven't had the chance to use smart pointers in actual development (the supervisior deems it too 'complex' and a waste of time). However, I planned to use them for my own stuff...

I have situations regarding de-initing a module after they are done, or when new data is loaded in. As I am using pointers, I find my code littered with check for null such as this...

// TODO: Reset all opened windows

// Deinit track result player
if (trackResultPlayer_)
 trackResultPlayer_->reset();

// disconnect track result player
disconnect(trackResultPlayer_);

disconnect(trackResultAnimator_);
}

if (videoPlayerWindow_)
{
 videoPlayerWindow_->reset();

 // Disconnect the video player window from source movie data
 disconnect(videoPlayerWindow_);
}

// Disconnect this module from its children as they would be connected again
disconnect(this);

If I am to use smart pointers, instead of raw pointers, how could this problem be alleviated?

+1  A: 

Smart pointer are primarily an instrument to manage the memory being pointed to. They are not meant as something, which would free you from the burden of NULL value checking...

In you example code, I don't see much potential for smart pointers reducing the code complexity, unless you move calls like videoPlayerWindow_->reset(), disconnect(videoPlayerWindow_) and such into the destructor of the class, videoPlayerWindow is an instance of.

Dirk
-1. Smart pointers are used (and recommended) for managing *any* type of resource that could be shared by multiple owners, not just memory. "They are not meant as something, which would free you from the burden of NULL value checking": in general that's true, but in this specific case the NULL checking is to see whether cleanup is necessary, which smart pointers with appropriate destructors *will* take care of. "I don't see much potential for smart pointers reducing the code complexity, unless..." LOL! Compare: "I don't see much point in food, unless you eat it".
j_random_hacker
I think I mentioned destructors. I cannot infer (from the code given by the OP) whether using destructors for the clean-up is actually a feasible way here.
Dirk
I guess we disagree then -- to me, the OP's code is crying out for the contents of those `if` blocks to be put in destructors (specifically, the destructor for the class whose pointer is being tested for NULL).
j_random_hacker
Sure enough, the clean solution would be to move the clean-up code into the appropriate destructors. On the other hand: he's talking about "de-initing a module", which I read as: "I have a bunch of pointers to objects in some global variables, which I need to dispose of safely now" (to me, the code looks that way). And that's what made me doubt that just adding a few lines to some destructor code here and there would be sufficient a refactoring to introduce the "proper" solution based on smart pointers.
Dirk
I see what you mean. Yes, doing things "the right way" would require more care and thinking than simply moving those code blocks into destructors -- in particular the OP would need to restructure things so that objects that depend on other objects contain them via smart pointers.
j_random_hacker
+2  A: 

Checks against NULL aren't a problem - and smart pointers don't meddle with that anyway.

Michael Foukarakis
+4  A: 

Make each of your classes implement a destructor which performs all the cleanup/deinitialization you need for that class.

Create an instance of the class, and wrap it in a boost::shared_ptr.

Then pass copies of that to every function which needs access to the instance.

And the smart pointer will ensure that once the object is no longer used (when all the shared pointers have been destroyed), the object they point to is destroyed. its destructor is run, and all the cleanup is executed.

As always in C++, use RAII whenever possible.

Whenever you have code like x.reset() or disconnect(x), the first thing you should do is ask yourself "doesn't this belong in a destructor?"

Further, whenever you use x->y() you should ask yourself:

  • Why is this a pointer? Couldn't I make do with a single instance allocated on the stack, and perhaps a few references to it?
  • If it has to be a pointer, why isn't it a smart pointer?
jalf