libc++源码分析之std::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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
// 定义类模板,T为要删除的指针类型
template <class T>
struct default_delete
{
constexpr default_delete() noexcept = default;
template <class U> default_delete(const default_delete<U>&) noexcept;
// 重写()操作符,外部调用该操作符将T类型的指针传递进来进行删除
void operator()(T*) const noexcept;
};

// 定义类模板,T为管理的指针类型,D为负责删除指针的结构体类型,默认实现为default_delete
template <class T, class D = default_delete<T>>
class unique_ptr
{
public:
typedef see below pointer; // 默认为T*,除非default_delete里定义了pointer类型
typedef T element_type; // 管理的指针类型
typedef D deleter_type; // 删除指针的结构体类型

// constructors
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; // removed in C++17

// destructor
~unique_ptr();

// assignment
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;

// observers
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;

// modifiers
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;

// constructors
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() { }

// destructor
~unique_ptr();

// assignment
unique_ptr& operator=(unique_ptr&& u) noexcept;
unique_ptr& operator=(nullptr_t) noexcept;

// observers
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;

// modifiers
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; // _Tp*
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 { }

// __pointer
_LIBCPP_ALLOCATOR_TRAITS_HAS_XXX(__has_pointer, pointer);

// remove_reference<_Alloc>::type获取到的是去掉引用后的真实类型,如果_Alloc不是引用,则返回_Alloc;
// __has_pointer是通过__void_t来判断一个类型内是否存在指定的子类型,如果在_Alloc中定义了子类型pointer,则匹配偏特化版本,返回true_type,否则匹配默认版本,返回false_type
template <class _Tp, class _Alloc,
class _RawAlloc = typename remove_reference<_Alloc>::type,
bool = __has_pointer<_RawAlloc>::value>
struct __pointer {
// 此时__pointer<_Tp, deleter_type>::type = deleter_type::pointer
using type = typename _RawAlloc::pointer;
};

// 偏特化,__has_pointer<_RawAlloc>::value>为false时匹配
template <class _Tp, class _Alloc, class _RawAlloc>
struct __pointer<_Tp, _Alloc, _RawAlloc, false> {
// 此时__pointer<_Tp, deleter_type>::type = _Tp*
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]());
}