boost::shared_ptr: When to use it and when NOT to use it.

Started by
11 comments, last by chairthrower 16 years ago
Hi! I find boost::shared_ptr very handy for liftetime management of objects and I feel like as if it would be a good idea to use it nearly everywhere to avoid having to deal with manual lifetime management (beware of cycles). But somethings sounds wrong to me in this idea. So, is there a good advide that says when and when NOT to use shared pointers or would it be a good idea to use them pratically everywhere? What are the downsides of using shared pointers, is the overhead large enough to be problematic? On the contrary, what are the downsides of not using shared pointers?
Advertisement
It's maybe a bad idea in cases where you're mostly going to end up just passing the raw pointer into a library or API that requires raw pointers. But for the majority of things you will probably want some form of smart pointer in modern C++ programming.
For most cases, the answer should probably be: "always", since smart pointers (obviously) avoid a lot of pain.

However, it has to be said that the particular example of boost::shared_ptr may not be the right thing to use if there are many assignments/copy operations in a place where performance is paramount.
boost::shared_ptr does all of its reference counting atomically (library calls on some platforms, locked atomic instructions on others). While that's a good thing regarding thread safety, it can be a performance killer if used uncritically everywhere.
The overhead should be neglegible under normal use, but one should probably avoid passing around a pointer several times in a loop that runs a few thousand times per frame, or putting 10k smart pointers into a std::vector and resize it afterwards (hey, don't ask me why I would want to do that...).
You should certainly use shared_ptr by default. However, definitely think twice in areas where that would involve a large number of pointer operations per frame. In particular, particle systems and geometry meshes should prefer to use raw pointers internally. Other than those situations, I've never seen shared_ptr near the top of my profiling report.

One thing to keep in mind: Whenever possible (which is nearly always), pass shared_ptrs as const references. This avoids incrementing, decrementing, and testing the use count.
An obvious answer is not to use it when you should use scoped_ptr instead, that is when you do not want your pointer to be copyable.

edit: This might interest you :
Boost documentation on Smart Pointer Timings

[Edited by - epsylon on April 22, 2008 11:26:59 AM]
Quote:Original post by epsylon
An obvious answer is not to use it when you should use scoped_ptr instead, that is when you do not want your pointer to be copyable.


Indeed, I also use weak_ptr very often.
Best regards, Omid
Quote:Original post by Trenki
So, is there a good advide that says when and when NOT to use shared pointers


When you wanted value semantics rather than reference semantics, particularly when pointing to polymorphic objects (there are far worse sins than using shared_ptr in this situation, though!).

*cough* value_ptr *cough* :)

When you have a resource that must go away promptly at a particular time.

When you want reference semantics (or value semantics, as noted).

When you actually need a garbage collected pointer.
Quote:Original post by NotAYakk
When you have a resource that must go away promptly at a particular time.

When you want reference semantics (or value semantics, as noted).

When you actually need a garbage collected pointer.


These seem like situations where shared_ptr is applicable (depending on one's definition of garbage collection), rather than the opposite, as the O.P wants?
No?

shared_ptr means that any object with a shared_ptr reference to the thing in question can extend it's lifetime.

shared_ptr uses pointer semantics on assign. Ie, a = b means that a points to what b pointed to, and a constructed from b means a refers to the same thing as b.

Reference semantics a=b means what a points to is given the value of what b points to, and a constructed from b means that a refers to the same thing as b.

Value semantics a=b means that the value of a changes to be the value of b, and a constructed from b means that the value of a becomes the same as the value of b.

pointer semantics != reference semantics != value semantics.

shared_ptr implements pointer semantics.

Lastly, shared_ptr is a reference counted pointer, not a garbage collected pointer. A loop of shared_ptrs will persist forever, even if they aren't reachable by any code.

But sure, they make great defaults!

This topic is closed to new replies.

Advertisement