libcxx memory中智能指针的实现

概述

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一样。

请添加图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值