Unique Flexibility

In my post the other day I off-handedly mentioned that “unique_ptr is much more flexible than shared_ptr”. No one took issue with that (either that or more likely no one read it) so this post might be unescessary but for completeness’ sake here we go…

In some ways unique_ptr is an inflexible beast since it has no copy constructor, you can only move it. But you can work around this quite easily if need be. Have a unique_ptr as a member in a class that you want to be copyable? If the type being pointed to is copyable (or cloneable more likely) then just copy it in your copy constructor so that the new object has it’s own unique copy of the member object stored in a new unique_ptr. You're jumping through some hoops but as these things go it’s not so bad.

Now look at shared_ptr. It has an inflexibility as well: once you put something in a shared_ptr you can’t get it back out. And even worse: you can’t work around this like you can with shortcoming of weak_ptr. So say you have a factory object that has a create method that returns a dynamically allocated object. How should it return said object? This is 2013 so there’s no way we’re returning a bare pointer (which still have their uses in 2013, just not as the return type of a factory method that needs to express the ownership semantics of the object created). If we return a shared_ptr then the caller is stuck always using shared_ptr to refer to that object. But if we return a unique_ptr then the caller can flexibly choose any way to store the object, even as a bare pointer if they have some perverse reason for doing so.

That’s not to say that there’s never a reason for a factory method to return a shared_ptr. If the factory has a collection of the created objects that’s used internally then you’ll probably want to store the objects in the collection using shared_ptr. Then, since once an object is in a shared_ptr it is always in a shared_ptr, you’ve got no choice but to return a shared_ptr. Of course you’re sharing the object so shared_ptrexpresses your intentions perfectly in this case. But, unless you’ve got a good reason to do otherwise, try and be nice to the clients of your class and give them the option to use what they want by returning a unique_ptr.

UPDATE: One strike against unique_ptr is when you intend to store the object in a shared_ptr and would thus use make_shared to get a small performance boost (one memory allocation versus two). By returning a unique_ptr you remove the caller’s ability to make use of make_shared. In these cases where the performance really matters return the shared_ptr using make_shared to create the underlying object. Or for heavily used code that needs it you could have multiple methods: one returning a unique_ptr for flexibility and the other returning a shared_ptr when the caller wants the performance and is sure to stick the object in a shared_ptr.

Advertisements

2 comments

  1. […] to say the code in question did not pass review. Between the unescessary copying of m_bar and the inflexiblility of the return type of GetBar there's a lot of confusion about object lifetimes and ownership […]

  2. […] objects – there is no danger of slicing. Of the smart pointers, unique_ptr is also the most flexible as a return type since you can transfer an object from a unique_ptr to a shared_ptr while going the […]

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: