定义
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
| template <class T> struct default_delete { constexpr default_delete() noexcept = default; template <class U> default_delete(const default_delete<U>&) noexcept; void operator()(T*) const noexcept; };
template <class T, class D = default_delete<T>> class unique_ptr { public: typedef see below pointer; typedef T element_type; typedef D deleter_type;
constexpr unique_ptr() noexcept; explicit unique_ptr(pointer p) noexcept; unique_ptr(pointer p, see below d1) noexcept; unique_ptr(pointer p, see below d2) noexcept; unique_ptr(unique_ptr&& u) noexcept; unique_ptr(nullptr_t) noexcept : unique_ptr() { } template <class U, class E> unique_ptr(unique_ptr<U, E>&& u) noexcept; template <class U> unique_ptr(auto_ptr<U>&& u) noexcept;
~unique_ptr();
unique_ptr& operator=(unique_ptr&& u) noexcept; template <class U, class E> unique_ptr& operator=(unique_ptr<U, E>&& u) noexcept; unique_ptr& operator=(nullptr_t) noexcept;
typename add_lvalue_reference<T>::type operator*() const; pointer operator->() const noexcept; pointer get() const noexcept; deleter_type& get_deleter() noexcept; const deleter_type& get_deleter() const noexcept; explicit operator bool() const noexcept;
pointer release() noexcept; void reset(pointer p = pointer()) noexcept; void swap(unique_ptr& u) noexcept; };
|
unique_ptr支持维护数组类型
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| template <class T, class D> class unique_ptr<T[], D> { public: typedef implementation-defined pointer; typedef T element_type; typedef D deleter_type;
constexpr unique_ptr() noexcept; explicit unique_ptr(pointer p) noexcept; unique_ptr(pointer p, see below d) noexcept; unique_ptr(pointer p, see below d) noexcept; unique_ptr(unique_ptr&& u) noexcept; unique_ptr(nullptr_t) noexcept : unique_ptr() { }
~unique_ptr();
unique_ptr& operator=(unique_ptr&& u) noexcept; unique_ptr& operator=(nullptr_t) noexcept;
T& operator[](size_t i) const; pointer get() const noexcept; deleter_type& get_deleter() noexcept; const deleter_type& get_deleter() const noexcept; explicit operator bool() const noexcept;
pointer release() noexcept; void reset(pointer p = pointer()) noexcept; void reset(nullptr_t) noexcept; template <class U> void reset(U) = delete; void swap(unique_ptr& u) noexcept; };
|
实现
内部类型定义
pointer
pointer类型默认是_Tp*,除非default_delete中定义了pointer类型。
1
| typedef typename __pointer<_Tp, deleter_type>::type pointer;
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| #define _LIBCPP_ALLOCATOR_TRAITS_HAS_XXX(NAME, PROPERTY) \ template <class _Tp, class = void> struct NAME : false_type { }; \ template <class _Tp> struct NAME<_Tp, typename __void_t<typename _Tp:: PROPERTY >::type> : true_type { }
_LIBCPP_ALLOCATOR_TRAITS_HAS_XXX(__has_pointer, pointer);
template <class _Tp, class _Alloc, class _RawAlloc = typename remove_reference<_Alloc>::type, bool = __has_pointer<_RawAlloc>::value> struct __pointer { using type = typename _RawAlloc::pointer; };
template <class _Tp, class _Alloc, class _RawAlloc> struct __pointer<_Tp, _Alloc, _RawAlloc, false> { using type _LIBCPP_NODEBUG_TYPE = _Tp*; };
|
_DeleterSFINAE
根据deleter_type的类型,定义了不同的子类型,通过enable_if在模板函数的参数Substitution时进行类型限定。在deleter_type是值类型时,定义__good_rval_ref_type,在deleter_type是引用类型时,定义了__bad_rval_ref_type。
1 2 3 4 5 6 7 8 9 10 11 12 13
| typedef __unique_ptr_deleter_sfinae<_Dp> _DeleterSFINAE;
template <bool _Dummy> using _LValRefType = typename __dependent_type<_DeleterSFINAE, _Dummy>::__lval_ref_type;
template <bool _Dummy> using _GoodRValRefType = typename __dependent_type<_DeleterSFINAE, _Dummy>::__good_rval_ref_type;
template <bool _Dummy> using _BadRValRefType = typename __dependent_type<_DeleterSFINAE, _Dummy>::__bad_rval_ref_type;
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| template <class _Deleter> struct __unique_ptr_deleter_sfinae { static_assert(!is_reference<_Deleter>::value, "incorrect specialization"); typedef const _Deleter& __lval_ref_type; typedef _Deleter&& __good_rval_ref_type; typedef true_type __enable_rval_overload; };
template <class _Deleter> struct __unique_ptr_deleter_sfinae<_Deleter const&> { typedef const _Deleter& __lval_ref_type; typedef const _Deleter&& __bad_rval_ref_type; typedef false_type __enable_rval_overload; };
template <class _Deleter> struct __unique_ptr_deleter_sfinae<_Deleter&> { typedef _Deleter& __lval_ref_type; typedef _Deleter&& __bad_rval_ref_type; typedef false_type __enable_rval_overload; };
|
_EnableIfDeleterDefaultConstructible
_EnableIfDeleterDefaultConstructible是用来限定deleter_type必须要有默认构造且不能是指针类型。
_Deleter得到的就是deleter_type类型,enable_if中判断如果_Deleter有默认构造且不是指针类型,才会有子类型type,否则_EnableIfDeleterDefaultConstructible不会被定义,则函数模板不匹配。
1 2 3 4 5
| template <bool _Dummy, class _Deleter = typename __dependent_type< __identity<deleter_type>, _Dummy>::type> using _EnableIfDeleterDefaultConstructible = typename enable_if<is_default_constructible<_Deleter>::value && !is_pointer<_Deleter>::value>::type;
|
_EnableIfDeleterConstructible
用来判断deleter_type是否有指定类型作为参数的构造函数。
1 2 3
| template <class _ArgType> using _EnableIfDeleterConstructible = typename enable_if<is_constructible<deleter_type, _ArgType>::value>::type;
|
_EnableIfMoveConvertible
判断_Uptr的pointer和当前的pointer两个类型能否进行转换,并且_Up不是数组。
1 2 3 4 5
| template <class _UPtr, class _Up> using _EnableIfMoveConvertible = typename enable_if< is_convertible<typename _UPtr::pointer, pointer>::value && !is_array<_Up>::value >::type;
|
_EnableIfDeleterConvertible
如果当前的deleter_type是引用,则判断当前的deleter_type和_UDel是否相同类型,相同类型的引用才允许;如果当前的deleter_type是值类型,则判断当前的deleter_type和_UDel是否可以进行转换。
1 2 3 4 5
| template <class _UDel> using _EnableIfDeleterConvertible = typename enable_if< (is_reference<_Dp>::value && is_same<_Dp, _UDel>::value) || (!is_reference<_Dp>::value && is_convertible<_UDel, _Dp>::value) >::type;
|
属性
_ptr
__compressed_pair是一个空类型优化的pair实现,__ptr_用来保存维护的指针和删除器。
1
| __compressed_pair<pointer, deleter_type> __ptr_;
|
构造函数
unique_ptr()
默认初始化pair,pointer()为创建_Tp*的空实例,__default_init_tag()为空类对象。
1 2 3
| template <bool _Dummy = true, class = _EnableIfDeleterDefaultConstructible<_Dummy> > unique_ptr() _NOEXCEPT : __ptr_(pointer(), __default_init_tag()) {}
|
unique_ptr(nullptr_t)
传nullptr和不传其实是一样的,都是做默认初始化,pointer()为创建_Tp*的空实例,__default_init_tag()为空类对象。
1 2 3 4
| template <bool _Dummy = true, class = _EnableIfDeleterDefaultConstructible<_Dummy> >
unique_ptr(nullptr_t) _NOEXCEPT : __ptr_(pointer(), __default_init_tag()) {}
|
unique_ptr(pointer __p)
该构造函数必须显示调用,__p就是需要管理的裸指针,__default_init_tag()为空类对象。pair的first就是__p指针,second就是空对象。
1 2 3
| template <bool _Dummy = true, class = _EnableIfDeleterDefaultConstructible<_Dummy> > explicit unique_ptr(pointer __p) _NOEXCEPT : __ptr_(__p, __default_init_tag()) {}
|
unique_ptr(pointer p, _LValRefType<_Dummy> d)
_LValRefType的类型根据deleter_type的类型走不同的特化版本, __p是需要管理的裸指针,而__d就是deleter_type类型的左值,使用这两个值重新创建pair。
1 2 3 4
| template <bool _Dummy = true, class = _EnableIfDeleterConstructible<_LValRefType<_Dummy> > > unique_ptr(pointer __p, _LValRefType<_Dummy> __d) _NOEXCEPT : __ptr_(__p, __d) {}
|
unique_ptr(pointer p, _GoodRValRefType<_Dummy> d)
_GoodRValRefType的类型只有在deleter_type的类型是值类型时才有定义,也就是说只有是deleter_type是值类型时,才允许其右值引用作为参数。
1 2 3 4 5 6 7
| template <bool _Dummy = true, class = _EnableIfDeleterConstructible<_GoodRValRefType<_Dummy> > > unique_ptr(pointer __p, _GoodRValRefType<_Dummy> __d) _NOEXCEPT : __ptr_(__p, _VSTD::move(__d)) { static_assert(!is_reference<deleter_type>::value, "rvalue deleter bound to reference"); }
|
unique_ptr(pointer p, _BadRValRefType<_Dummy> d) = delete
当deleter_type的类型为引用类型时,才定义了_BadRValRefType,也就是说当传递进来的deleter_type是引用类型时,则不允许传递右值参数进来。
1 2 3
| template <bool _Dummy = true, class = _EnableIfDeleterConstructible<_BadRValRefType<_Dummy> > > unique_ptr(pointer __p, _BadRValRefType<_Dummy> __d) = delete;
|
unique_ptr(unique_ptr&& __u)
移动构造,__u释放管理的裸指针,将其转交给当前对象,将__u的deleter也进行转发成deleter_type类型给当前对象。
1 2 3
| unique_ptr(unique_ptr&& __u) _NOEXCEPT : __ptr_(__u.release(), _VSTD::forward<deleter_type>(__u.get_deleter())) { }
|
unique_ptr(unique_ptr<_Up, _Ep>&& __u) _NOEXCEPT
接收一个类型不一致的右值引用,如果__u中维护的裸指针类型和当前对象中定义的类型可以转换,并且__u中的类型不是数组,则_EnableIfMoveConvertible满足;如果__u中维护的deleter_type和当前的deleter_type可以转换,那么_EnableIfDeleterConvertible满足。__u释放管理的裸指针,将其转交给当前对象,将__u的deleter也按照自身的类型转发给当前对象。
1 2 3 4 5 6
| template <class _Up, class _Ep, class = _EnableIfMoveConvertible<unique_ptr<_Up, _Ep>, _Up>, class = _EnableIfDeleterConvertible<_Ep> > unique_ptr(unique_ptr<_Up, _Ep>&& __u) _NOEXCEPT : __ptr_(__u.release(), _VSTD::forward<_Ep>(__u.get_deleter())) {}
|
析构函数
~unique_ptr()
1
| ~unique_ptr() { reset(); }
|
赋值函数
operator=(unique_ptr&& __u)
接收一个右值引用,__u释放管理的裸指针,当前对象通过reset方法重新管理该裸指针,将__u的deleter也进行转发给当前对象。
1 2 3 4 5
| unique_ptr& operator=(unique_ptr&& __u) _NOEXCEPT { reset(__u.release()); __ptr_.second() = _VSTD::forward<deleter_type>(__u.get_deleter()); return *this; }
|
operator=(unique_ptr<_Up, _Ep>&& __u)
接收一个类型不一致的右值引用的赋值。同上面的构造函数。
1 2 3 4 5 6 7 8 9
| template <class _Up, class _Ep, class = _EnableIfMoveConvertible<unique_ptr<_Up, _Ep>, _Up>, class = _EnableIfDeleterAssignable<_Ep> > unique_ptr& operator=(unique_ptr<_Up, _Ep>&& __u) _NOEXCEPT { reset(__u.release()); __ptr_.second() = _VSTD::forward<_Ep>(__u.get_deleter()); return *this; }
|
operator=(nullptr_t) _NOEXCEPT
1 2 3 4
| unique_ptr& operator=(nullptr_t) _NOEXCEPT { reset(); return *this; }
|
操作函数
operator->() const _NOEXCEPT
定义操作符->,返回__ptr_.first(),可以直接通过->访问内部裸指针的相关方法。
1 2 3
| pointer operator->() const _NOEXCEPT { return __ptr_.first(); }
|
operator() const*
定义操作符,返回_ptr.first(),可以直接通过*来获取内部裸指针对应的对象值。返回_Tp的左值引用类型。
1 2 3 4
| typename add_lvalue_reference<_Tp>::type operator*() const { return *__ptr_.first(); }
|
pointer get() const _NOEXCEPT
获取内部的裸指针。
1 2 3
| pointer get() const _NOEXCEPT { return __ptr_.first(); }
|
get_deleter() _NOEXCEPT
获取内部的deleter
1 2 3
| deleter_type& get_deleter() _NOEXCEPT { return __ptr_.second(); }
|
get_deleter() const _NOEXCEPT
获取内部的deleter,返回的是常亮。
1 2 3
| const deleter_type& get_deleter() const _NOEXCEPT { return __ptr_.second(); }
|
perator bool() const _NOEXCEPT
定义bool操作符,对unique_ptr的bool化是判断内部的__ptr.first是否为空。
1 2 3
| operator bool() const _NOEXCEPT { return __ptr_.first() != nullptr; }
|
get_deleter() const _NOEXCEPT
获取内部的deleter,返回的是常亮。
1 2 3
| const deleter_type& get_deleter() const _NOEXCEPT { return __ptr_.second(); }
|
release() _NOEXCEPT
释放裸指针的管理权,从__ptr中取出裸指针,将其返回,在__ptr_中放入一个空的裸指针。
1 2 3 4 5
| pointer release() _NOEXCEPT { pointer __t = __ptr_.first(); __ptr_.first() = pointer(); return __t; }
|
reset(pointer __p = pointer()) _NOEXCEPT
接收一个新的裸指针,如果没传参数默认为空的裸指针;将旧的裸指针从__ptr_中取出来,将新的裸指针放入到__ptr_中;然后调用deleter删除旧的裸指针。
1 2 3 4 5 6
| void reset(pointer __p = pointer()) _NOEXCEPT { pointer __tmp = __ptr_.first(); __ptr_.first() = __p; if (__tmp) __ptr_.second()(__tmp); }
|
swap(unique_ptr& __u) _NOEXCEPT
unique_ptr的交换就是把__ptr_进行交换。将pair中的裸指针和deleter进行交换。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| void swap(unique_ptr& __u) _NOEXCEPT { __ptr_.swap(__u.__ptr_); }
void swap(__compressed_pair& __x) _NOEXCEPT_(__is_nothrow_swappable<_T1>::value && __is_nothrow_swappable<_T2>::value) { using _VSTD::swap; swap(first(), __x.first()); swap(second(), __x.second()); }
|
swap(unique_ptr<_Tp, _Dp>& __x, unique_ptr<_Tp, _Dp>& __y) _NOEXCEPT
1 2 3 4 5 6 7
| template <class _Tp, class _Dp> inline typename enable_if< __is_swappable<_Dp>::value, void >::type swap(unique_ptr<_Tp, _Dp>& __x, unique_ptr<_Tp, _Dp>& __y) _NOEXCEPT {__x.swap(__y);}
|
operator==
定义==比较操作符,直接比较内部的裸指针是否相等。其它比较符都一样都是直接比较裸指针。
1 2 3 4
| template <class _T1, class _D1, class _T2, class _D2> inline _LIBCPP_INLINE_VISIBILITY bool operator==(const unique_ptr<_T1, _D1>& __x, const unique_ptr<_T2, _D2>& __y) {return __x.get() == __y.get();}
|
工厂函数
make_unique(Args&&… args)
使用该函数创建时,_Tp不支持为数组。使用_Args参数来new一个_Tp对象,创建一个unique_ptr来维护该对象。
1 2 3 4 5 6 7
| template<class _Tp, class... _Args> inline typename __unique_if<_Tp>::__unique_single make_unique(_Args&&... __args) { return unique_ptr<_Tp>(new _Tp(_VSTD::forward<_Args>(__args)...)); }
|
make_unique(size_t n)
该函数支持数组类型的创建,__n是数组的长度。
1 2 3 4 5 6 7 8
| template<class _Tp> inline typename __unique_if<_Tp>::__unique_array_unknown_bound make_unique(size_t __n) { typedef typename remove_extent<_Tp>::type _Up; return unique_ptr<_Tp>(new _Up[__n]()); }
|