Use unique_ptr when you want a single pointer to an object that will be reclaimed when that single pointer is destroyed. Use shared_ptr when you want multiple pointers to the same resource.
unique_ptr is a new facility with a similar functionality, but with improved security. auto_ptr is a smart pointer that manages an object obtained via new expression and deletes that object when auto_ptr itself is destroyed.
A unique_ptr does not share its pointer. It cannot be copied to another unique_ptr , passed by value to a function, or used in any C++ Standard Library algorithm that requires copies to be made. A unique_ptr can only be moved.
Because the unique pointer does not have a copy constructor. Hence you cannot pass it by value, because passing by value requires making a copy. Actually that is nearly the sole and whole point of a unique_ptr .
It's not possible to create something like unique_ptr
without C++0x (where it's part of the standard library, and so Boost doesn't need to provide it).
Specifically without rvalue references, which are a feature in C++0x, a robust implementation of unique_ptr
is impossible, with or without Boost.
In C++03, there are a few possible alternatives, although each have their flaws.
boost::shared_ptr
is probably the simplest replacement in terms of capabilites. You can safely use it anywhere you'd otherwise use a unique_ptr
and it'd work. It just wouldn't be as efficient, because of the added reference counting. But if you're looking for a simple drop-in replacement that's able to handle everything unique_ptr
can do, this is probably your best bet. (Of course, a shared_ptr
can do a lot more as well, but it can also simply be used as a drop-in replacement for unique_ptr
.)boost::scoped_ptr
is similar to unique_ptr
but does not allow transfer of ownership. It works great as long as the smart pointer is meant to retain exclusive ownership throughout its lifetime.std::auto_ptr
works very similar to unique_ptr
, but has a few limitations, mainly that it can not be stored in standard library containers. If you're simply looking for a pointer that allows transfer of ownership, but which is not meant to be stored in containers or copied around, this is probably a good bet.Starting from Boost 1.57 there's an official unique_ptr
implementation in Boost.Move library.
From the documentation:
(...) a drop-in replacement for std::unique_ptr, usable also from C++03 compilers.
The code is available in <boost/move/unique_ptr.hpp>
header file and lives in boost::movelib
namespace. Moreover, Boost.Move library provides make_unique()
factory function in <boost/move/make_unique.hpp>
, also in boost::movelib
namespace.
Hence the example from the question could be implemented this way:
#include <boost/move/unique_ptr.hpp>
using boost::movelib::unique_ptr;
unique_ptr<Base> create_base()
{
return unique_ptr<Base>(new Derived);
}
See a live example on Wandbox. Note that the code compiles fine with gcc 4.6.4 in C++98 mode (!).
What's interesting in boost::movelib::unique_ptr
when applied to your case with base/derived classes, the implementation provides a compile-time check for the declaration of a virtual destructor in the base class. If you happen to omit it the code won't compile (click the "Run (...)" button to see the compiler error message).
One minor issue is that includes come from boost/move
directory but the code lives in boost::movelib
namespace (subtle difference but can be annoying).
See also a thread on boost mailing list for more details.
Thanks to Ion Gaztañaga for this absolutely unique and useful piece of code.
You might want to try Howard Hinnant's 'proof of concept' unique_ptr<>
implementation for C++03 (disclaimer - I haven't):
One of his examples is returning a unique_ptr<int>
:
unique_ptr<int> factory(int i)
{
return unique_ptr<int>(new int(i));
}
How about unique_ptr
from the interprocess library?
I've used Howard Hinnant's unique_ptr. If you are not really good at reading crazy metaprogramming errors from you compiler you might want to steer clear. It however does act just like a unique_ptr in 90% of the cases.
Otherwise I'd suggest passing paramters as boost::scoped_ptr&
and swap internally to steal ownership. To get unique_ptr style return values use an auto_ptr
. Capture the auto_ptr
return value in a shared_ptr
or scoped_ptr
to avoid using the auto_ptr
directly.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With