What is std::unique_ptr
Smart Pointer
As we know, using raw pointer has the opportunity to reault in memory leak if we forget to delete it or delete it with a wrong way. Therefore, there are potential risks.
In traditional C++, there is std::auto_ptr
but it will transfer the ownership of the target object after copying std::auto_ptr
. It means that the original auto_ptr is deprecated and it couldn’t be used anymore, but we don’t have methods to avoid actually. It depends to programmers’ self-consciousness. It is also a risk.
std::unique_ptr
After C++11, std::unique_ptr
is used widely and it’s often a best practice for controlling the life cycle of an object. It means the unique handler leveraging the ownership of the target object. The ownership can’t be copied it can only be transformed by std::move
.
The declaration of std::unique_ptr
The design philosophy of std::unique_ptr
is simple. It’s just a wrapper of a raw pointer and it controls the life cycle of the target object by RAII (especially within its destructor).
The implementation of std::unique_ptr
shown in this page is from MSVC STL.
1 |
|
1 |
|
default_delete
is a default deleter for the target type _Ty
.
There is an interesting point here:
The deleter is set in the template argument list instead of as a member variable of unique_ptr
. The purpose of this kind of implementation is to save abstraction overhead as far as possible. It indicates the idea of zero overhead abstraction in C++.
The implementation of std::unique_ptr
1 |
|
Ignore the implementation of
template <class _Ty, class _Dx> class unique_ptr<_Ty[], _Dx>
.
The implementation of _Compressed_pair
_Zero_then_variadic_args_t
indicates it will all used to construct_Ty2
object with all given arguments._One_then_variadic_args_t
indicates that the_Ty1
object is constructed with the first argument and the_Ty2
object is constructed with the rest arguments.
1 |
|
1 |
|
Note that _Compressed_pair<_Ty1, _Ty2, true>
is used for empty base class optimization. It indicates we don’t have to allocate a memory space for it.
How to understand template <class _Ty1, class _Ty2, bool = is_empty_v<_Ty1> && !is_final_v<_Ty1>>
?
- If
is_empty_v<_Ty1>
is false, we have to allocate a memory space for_Ty1
(deleter) in_Compressed_pair<_Ty1, _Ty2, false>
. - If
is_final_v<_Ty1>
is true,_Compressed_pair
cann’t inherit from_Ty1
hence we have to allocate a memory space for it in_Compressed_pair<_Ty1, _Ty2, false>
.
The implementation of std::make_unique
1 |
|
1 |
|
It indicates that it’s available to write below code:
1 |
|
But it’s not allowed that:
1 |
|