概述
libcxx 中 shared_ptr 本身只是一个代理类,C++11 的泛型都是用模板实现的。
shard_ptr、unique、weak_ptr 这3个类的实现都是在memory 文件中。
属于使用时,用#include <memory>
声明类型
原理
memory文件包含memory接口和内部逻辑,例如shard_ptr、unique、weak_ptr属于接口
shared_ptr实现
shared_ptr实现就是内部控制一个引用计数器
make_shared的实现
make_shared与new 一个指针在创建shared_ptr哪个效率高?
template<class _Tp, class ..._Args>
inline _LIBCPP_INLINE_VISIBILITY
typename enable_if
<
!is_array<_Tp>::value,
shared_ptr<_Tp>
>::type
make_shared(_Args&& ...__args) //右值引用,避免调用拷贝与赋值
{
static_assert(is_constructible<_Tp, _Args...>::value, "Can't construct object in make_shared");
typedef __shared_ptr_emplace<_Tp, allocator<_Tp> > _CntrlBlk;
typedef allocator<_CntrlBlk> _A2;
typedef __allocator_destructor<_A2> _D2;
_A2 __a2;
unique_ptr<_CntrlBlk, _D2> __hold2(__a2.allocate(1), _D2(__a2, 1)); //申请1个——Tp对象内存空间,同时创建一个的析构器
::new(__hold2.get()) _CntrlBlk(__a2, _VSTD::forward<_Args>(__args)...); //1、__hold2.get()获取pointer,2、__shared_ptr_emplace类、forward转发
//typedef _LIBCPP_NODEBUG_TYPE typename __pointer_type<_Tp, deleter_type>::type pointer;
_Tp *__ptr = __hold2.get()->get();
return shared_ptr<_Tp>::__create_with_control_block(__ptr, __hold2.release());
}
pointer allocate(size_type __n, allocator<void>::const_pointer = 0)
{
if (__n > max_size())
__throw_length_error("allocator<T>::allocate(size_t n)"
" 'n' exceeds maximum supported size");
return static_cast<pointer>(_VSTD::__libcpp_allocate(__n * sizeof(_Tp), _LIBCPP_ALIGNOF(_Tp)));
}
template<class _Yp, class _CntrlBlk>
static shared_ptr<_Tp>
__create_with_control_block(_Yp* __p, _CntrlBlk* __cntrl)
{
shared_ptr<_Tp> __r;
__r.__ptr_ = __p;
__r.__cntrl_ = __cntrl;
__r.__enable_weak_this(__r.__ptr_, __r.__ptr_);
return __r;
}
第二种
shared_ptr<Object> p = shared_ptr<Object>(new Object());
//new 创建Object对象,申请内存,在shared_ptr构造函数->赋值构造函数。
template<class _Tp>
template<class _Yp>
shared_ptr<_Tp>::shared_ptr(_Yp* __p,
typename enable_if<is_convertible<_Yp*, element_type*>::value, __nat>::type)
: __ptr_(__p)
{
unique_ptr<_Yp> __hold(__p);
typedef typename __shared_ptr_default_allocator<_Yp>::type _AllocT;
typedef __shared_ptr_pointer<_Yp*, default_delete<_Yp>, _AllocT > _CntrlBlk;
__cntrl_ = new _CntrlBlk(__p, default_delete<_Yp>(), _AllocT()); //new __shared_ptr_pointer
__hold.release(); //
__enable_weak_this(__p, __p);
}
template<class _Tp>
inline
shared_ptr<_Tp>&
shared_ptr<_Tp>::operator=(const shared_ptr& __r) _NOEXCEPT //左值引用
{
shared_ptr(__r).swap(*this);
return *this;
}
多线程如何保证引用计数器同步的?
引用计数实际上是存放在基类__shared_count->__shared_owners_成员
下面是__shared_count的成员方法__add_shared()
,__release_shared()
实现
void __add_shared() _NOEXCEPT {
__libcpp_atomic_refcount_increment(__shared_owners_);
}
_LIBCPP_INLINE_VISIBILITY
bool __release_shared() _NOEXCEPT {
if (__libcpp_atomic_refcount_decrement(__shared_owners_) == -1) {
__on_zero_shared();
return true;
}
return false;
}
template <class _Tp>
inline _LIBCPP_INLINE_VISIBILITY _Tp
__libcpp_atomic_refcount_increment(_Tp& __t) _NOEXCEPT
{
#if defined(_LIBCPP_HAS_BUILTIN_ATOMIC_SUPPORT) && !defined(_LIBCPP_HAS_NO_THREADS)
return __atomic_add_fetch(&__t, 1, __ATOMIC_RELAXED);// 原子操作定义于头文件 <stdatomic.h>
// 参数1.指向要修改的原子对象的指针 参数2.要加到存储于原子对象中的值的值 参数3.操作的内存同步顺序
#else
return __t += 1;
#endif
}
template <class _Tp>
inline _LIBCPP_INLINE_VISIBILITY _Tp
__libcpp_atomic_refcount_decrement(_Tp& __t) _NOEXCEPT
{
#if defined(_LIBCPP_HAS_BUILTIN_ATOMIC_SUPPORT) && !defined(_LIBCPP_HAS_NO_THREADS)
return __atomic_add_fetch(&__t, -1, __ATOMIC_ACQ_REL);
#else
return __t -= 1;
#endif
}
unique实现
make_unique
c++14提供3种创建make_unique方法
template<class T, class... Args> unique_ptr<T> make_unique(Args&&... args); // C++14
template<class T> unique_ptr<T> make_unique(size_t n); // C++14
template<class T, class... Args> unspecified make_unique(Args&&...) = delete; // C++14, T == U[N]
//实现
template<class _Tp, class... _Args>
inline _LIBCPP_INLINE_VISIBILITY
typename __unique_if<_Tp>::__unique_single
make_unique(_Args&&... __args)
{
return unique_ptr<_Tp>(new _Tp(_VSTD::forward<_Args>(__args)...)); //forward 完美转发,使用时必须指定参数
}
template<class _Tp>
inline _LIBCPP_INLINE_VISIBILITY
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]()); //创建n个对象的数据组
}
template<class _Tp, class... _Args>
typename __unique_if<_Tp>::__unique_array_known_bound
make_unique(_Args&&...) = delete; //禁止使用右值引用,创建unique
unique_ptr的赋值对象都是右值引用,左值引用被屏蔽掉了。
unique_ptr 的成员变量被保存到__compressed_pair这里,同时支持自定义删除器
__compressed_pair<pointer, deleter_type> _ptr;
weak_ptr实现
weak_ptr 是shared_ptr的友元类。
shared_ptr可以访问weak_ptr->__cntrl_成员变量。
weak_ptr功能比较简单 包含两个成员变量
element_type* __ptr_;
__shared_weak_count* __cntrl_;
使用的引用计数器与shared_ptr一样。