C++11 introduces many significant improvements to the language and runtime. One
of the most important is to do with memory management - specifically, smart
unique_ptr makes managing dynamically allocated memory safe and
Instead of using a bare pointer type in C++, the modern C++11 style is now to
std::unique_ptr. This class will automatically free the allocated memory
once the variable goes out of scope. This is the simplest of the new smart
pointer types in C++11.
Whereas before, you might write:
you can now write:
std::unique_ptr class enforces several useful properties:
- only a single reference to the allocated object can be active at any given time
- the object will be deleted when the smart pointer goes out of scope
- the object will be deleted if an exception is thrown
It bears spelling this out: when used correctly,
std::unique_ptr can virtually
eliminate memory leaks. This makes the cost of the conversion process
unique_ptr type is templated over the pointer type, and its constructor
takes the allocated pointer returned from the
new operator. And because the
operator->() is overloaded, the smart pointer object can be used just
like a regular pointer.
Note 1: For Boost users, this is almost the same as the
Note 2: This class supercedes the
std::auto_ptr, which was deprecated in C++11.
Note 3: When invoking
std::unique_ptr methods on the smart pointer itself,
remember to use the dot
. operator. When invoking methods on the object pointer,
use the arrow
-> operator as you normally would (since it is overloaded to return the underlying object pointer).
Once the variable goes out of scope,
delete will be called to release the memory,
and the destructor will be invoked as usual, as this simple example shows:
The output is:
+++ main() +++ Foo::Foo() ... Foo::process() --- main() --- Foo::~Foo()
If you wish to delete the object before the holding pointer goes out of scope,
you can use the
reset() method on the smart pointer:
(Notice that methods invoked on the smart pointer itself use
methods on the target object use the overloaded dereference operator
This results in the trace:
+++ main() +++ Foo::Foo() ... Foo::process() ... obj: 0x7fb733c047c0 --- Foo::~Foo() --- main()
The simple difference here is that the object’s destructor is called before
the end of
main, since we invoke
reset() explicitly. Above, the destructor
is invoked after the end of
main, since the smart pointer is going out of
scope. This is a subtle but important point.
What happens if we try to assign this pointer to another smart pointer?
We get a meaningful compiler error:
cpp11_unique_ptr_ex2.cpp:27:10: error: object of type 'std::__1::unique_ptr<Foo, std::__1::default_delete<Foo> >' cannot be assigned because its copy assignment operator is implicitly deleted obj2 = obj;
The compiler is enforcing the unique ownership semantics, so we can’t accidentally do the wrong thing.
But if we can’t assign these unique pointers, how do we move them around? Using
the new explicit move support in C++11 (which is itself a large and complex
topic). This transfers ownership of the pointer from one
The output of the test program shows the result (we can access the enclosed pointer
+++ main() +++ Foo::Foo() Before move: obj1:0x7fa8b9d00000 obj2:0x0 After move: obj1:0x0 obj2:0x7fa8b9d00000 --- main() --- Foo::~Foo()
Notice how only one
Foo instance was created, and that its pointer value moved
obj2? After the
move operation, the pointer in
obj1 is null.
Thus move semantics preserve the single owner invariant.
std::unique_ptr class also has explicit support for handling arrays of
pointers. It is not a replacement for
std::vector, but depending on your
requirements, this array support can be very useful.
Returning objects from functions
unique_ptr idiom is especially useful when you need to return an allocated
resource from a function or method, but don’t want to worry about having to free
the object later. This sample function returns a unique pointer to the caller,
transferring ownership by implicitly moving the result:
The object will be freed when the caller stops referencing it.
The move support enables efficient storage of
unique_ptr managed objects in
containers (one of the limitations of the deprecated
std::auto_ptr). If you
have a vector of pointers to objects, you need to carefully manage ownership
(eg. does the creator or the container own the allocations?) and manually free
them. But with
unique_ptr, instead of:
we can write:
then when creating the object, we use the explicit move support to pass ownership of the object to the container (and avoid any reallocations or temporaries):
vector goes out of scope, its destructor will in turn release all
unique_ptr instances it owns. This automatic releasing of resources
can save a great deal of debugging pain and potential memory leaks.
The benefits of using
std::unique_ptr are many. And fortunately, the cost of
using this support is minimal (though for embedded systems, needs to be
carefully considered). The is a memory overhead of one word per instance (eg. 8
bytes on a 64-bit architecture).
The code generated for a method invocation involves an extra pointer indirection, the overhead which seems to be in the order of 2-3% (based on some simplistic tests; see the repo for full source).
The process to convert existing code which uses manual memory management to using smart pointers may not be trivial, but the long-term benefits of more maintainable and reliable code are frequently worth the investment of time. Going through the process may well highlight complex memory management strategies or error-prone code, and eliminate even more problems.
- Search for allocations using
- Remove calls to
Other smart pointer types
Now that you have a grasp on single owner smart pointers, you can read about shared pointers which can have many owners, and weak pointers: