Modern C++ - Smart pointers
Smart pointers: ensure that programs are free of memory and resource leaks and are exception-safe.
unique_ptr: Allows exactly one owner of the underlying pointer. Cannot be copied.
shared_ptr: Reference-counted smart pointer. The raw pointer is not deleted until all
shared_ptrowners have gone out of scope or have otherwise given up ownership.
weak_ptr: provides access to an object that is owned by one or more
shared_ptrinstances, but does not participate in reference counting. Useful to break circular refernce.
Smart pointers are crucial to the RAII (Resource Acquisition Is Initialization) programming idiom (ensure that resource acquisition occurs at the same time that the object is initialized, so that all resources for the object are created and made ready in one line of code)
std::unique_ptr<A> p(new A());
NOTE: Do not use the
malloc expression on the smart pointer itself.
Different from Java/C#: no separate garbage collector runs in the background; memory is managed through the standard C++ scoping rules so that the runtime environment is faster and more efficient.
std::unique_ptr<Foo> v = std::make_unique<Foo>(); // or auto v = std::make_unique<Foo>();
If it is never
std::moved to or from another
std::unique_ptr, it likely should not be a
std::unique_ptr conveys transferrable ownership which is unhelpful if ownership isn't being transferred.
The stored pointer points to the object managed by the
unique_ptr, if any, or to
nullptr if the
unique_ptr is empty.
std::unique_ptr::get does not make
unique_ptr release ownership of the pointer (i.e., it is still responsible for deleting the managed data at some point). Therefore, the value returned by this function shall not be used to construct a new managed pointer.
In order to obtain the stored pointer and release ownership over it, call
a call to
std::move isn’t actually a move itself, it’s just a cast to an rvalue-reference. It’s only the use of that reference by a move constructor or move assignment that does the work.
std::vector<int> foo = GetSomeInts(); std::move(foo); // Does nothing. // Invokes std::vector<int>’s move-constructor. std::vector<int> bar = std::move(foo);
Not pointers or references to
unique_ptr (i.e. use
std::unique_ptr<Foo>*). For example:
// unique_ptr as the return value std::unique_ptr<Foo> GetFoo(); // unique_ptr as an argument void Bar(std::unique_ptr<Foo> arg);
Even without explicitly deleting the copy constructor and copy assignment operator. Because
std::unique_ptr is not copyable.
When creating a new object to store in a
The only exception to this rule is when implementing a factory function that uses a
private constructor. In this case, you have to use new, but you should immediately wrap the result using