std::unique_ptr is a small, fast, move-only smart pointer for managing resources with exclusive-ownership semantics.
Some facts:
std::unique_ptrembodies exclusive ownership semantics: a non-nullstd::unique_ptrowns what it points to- Moving a
std::unique_ptrtransfers ownershiip from the source pointer to the destination pointer - Copying a
std::unique_ptrisn’t allowed (it’s move-only type) - Upong destruction, a non-null
std::unique_ptrdestroys its resource by calling its deleter (by default the deleter simply appliesdeleteto the raw pointer inside thestd::unique_ptr) std::unique_ptrcan easily and efficiently converts to astd::shared_ptr
Factory functions and Pimpl Idiom are two common use case for std::ptrs. For example, supporse we have a hierarchy for types of investments (e.g., stocks, bonds, real estate, etc.) with a factory function alllocating an object on the heap and returning a pointer to it:
|
|
By the help of std::unique_ptr, clients will no longer worry about deleting it:
|
|
Callers can also take use of std::unique_ptr’s feature to adapt it to its more flexible sibling std::shared_ptr:
|
|
Implementation
For C++11, we can implement the factory function this way:
|
|
In C++14, we could use function return type deduction to make it simpler and more encapsulated:
|
|
It is worth thinking about the size impact on a std::unique_ptr after introducing a custome deleter:
- if the deleter is a function pointer, the size of a
std::unique_ptrgenerally grow from one (the size of a raw pointer) to two - if the deleter is a function object, the change in size depends on how much state is stored in the function object
- Stateless function objects (e.g., from lambda expressions with no captures) typically incur no size penalty when used as deleters (still one word)
- Function object deleters with extensive state can yield
std::unique_ptrobjects of significant size.
Two forms
std::unique_ptr comes in two forms
std::unique_ptr<T>for individule objects, which lacks indexing operator (operator[])std::unique_ptr<T[]>for arrays, which lacks dereferencing operators (operator*andoperator->)
Generally, std::array, std::vector, and std::string are always better data structure choices than raw arrays, so the only situation where std::unique_ptr<T[]> makes sense would be when we’re using a C-like API that returns a raw pointer to a heap array that we assume ownership of.