I'm falling out with shared_ptr

Published May 01, 2009
Advertisement

I'm falling out with shared_ptr

Today's insight is short. Don't go crazy with the shared_ptr template. It's got its uses but don't overuse it. I did it. I'm paying for it. My code looks horrible and I get extra work overhead cleaning it up. The lesson is simple:

Only use shared_ptr when responsibility for the allocated object is shared.


How do you think it got its name? Whenever you can distinguish one single entity that is responsible for creation and destruction you don't need a shared_ptr. So what's the problem? Well, for one it's horrible to write so you'll end up with hundreds of typedefs to keep it down. An extreme example (very common in my code though):

std::map< std::string, std::tr1::shared_ptr< SomeClass >> stringToClassMap;

So easy to avoid since I almost always create and destroy the objects in ctor/dtor pair anyway.

Further, shared_ptr ruins my spartan include structure. Imagine this is in a header:

class SomeClass;SomeClass *someObject;

This does not require any extra includes. The forward declaration of SomeClass is enough. However:

std::tr1::shared_ptr someObject;

This requires that the full declaration of SomeClass is included because the compiler needs it to specialize the template. The result is longer compile times since my headers gets bloated with extra inclusions.

This may have come out as me running a hate campaign against shared_ptr. I don't, but seeing my own mistakes I try to preach modesty in its use. It's still very useful when passing heap objects around that don't have a distinct owner/manager and needs to be reference counted. Just trust in your ability as a programmer to free what you allocate and you won't need it most of the time.

Previous Entry Contemplation
0 likes 5 comments

Comments

evolutional
I always typedef it when I'm using it.


class Object { ... };

typedef boost::shared_ptr<Object> ObjectPtr;

void SomeFunctionThatNeedsAnObjectPointer( ObjectPtr myobject );

May 01, 2009 05:14 AM
Staffan E
Yes, typedefs makes typing easier. My first argument is not very strong. I forgot to mention that the root of this lashing out is that I'm (at times) almost religiously devoted towards keeping my include chains short.

A day out in the open with lots of sunshine has lessened my fury somewhat. But I still feel that I've overused the buggers and I still need to clean out my code.
May 01, 2009 11:29 AM
Deyja
Consider boost::intrusive_ptr instead.

It works nicely with nothing but a forward declared type (So long as the add_ref/release functions are in scope for any code that actually uses it.)

My only gripe with smart pointers in general is that operator-> on iterators doesn't reach through them. You end up having to do things like (*iterator)->
May 10, 2009 08:54 PM
nuvem
Quote:Original post by Deyja
Consider boost::intrusive_ptr instead.

It works nicely with nothing but a forward declared type (So long as the add_ref/release functions are in scope for any code that actually uses it.)

My only gripe with smart pointers in general is that operator-> on iterators doesn't reach through them. You end up having to do things like (*iterator)->


Actually, shared_ptr does not instantiate or access members of the type, and therefore will function with forward declarations.

For the latter, take a look at boost:ptr_container.
May 10, 2009 09:24 PM
Bakura
std::unique_ptr is the way to go ^^ (or alternatively boost::scoped_ptr).
June 09, 2009 03:57 PM
You must log in to join the conversation.
Don't have a GameDev.net account? Sign up!
Profile
Author
Advertisement
Advertisement