[C++]智能指针的实现

本文探讨C++中智能指针的实现,重点关注构造函数、引用计数和赋值运算符。通过分析源码,解释了如何使用原子操作管理引用计数,以及在对象复制过程中的引用计数处理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

注:源码来源为 llvm/llvm-project

使用智能指针时我们所包含的头文件为<memory>,而关于shared_ptr<T>的类定义实际上在shared_ptr.h中,为了便于理解,此处仅从源码中截取出其部分构造函数、成员变量以及重载的赋值运算符:

template<class _Tp>
class shared_ptr
{
private:
    element_type*      __ptr_;		// 所管理的对象内存的指针
    __shared_weak_count* __cntrl_;	// 引用计数相关的指针
......

	shared_ptr() _NOEXCEPT : __ptr_(nullptr), __cntrl_(nullptr) { }
	
	explicit shared_ptr(_Yp* __p) : __ptr_(__p) {	// 传入堆内存指针的构造函数
        unique_ptr<_Yp> __hold(__p);	// 此处使用 unique_ptr 是和目的?
        typedef typename __shared_ptr_default_allocator<_Yp>::type _AllocT;
        typedef __shared_ptr_pointer<_Yp*, __shared_ptr_default_delete<_Tp, _Yp>, _AllocT > _CntrlBlk;
        __cntrl_ = new _CntrlBlk(__p, __shared_ptr_default_delete<_Tp, _Yp>(), _AllocT());
        __hold.release();
        __enable_weak_this(__p, __p);
    }
    
	shared_ptr(const shared_ptr& __r) _NOEXCEPT	// 复制构造函数
        : __ptr_(__r.__ptr_), __cntrl_(__r.__cntrl_)
    {
        if (__cntrl_)
            __cntrl_->__add_shared();	// 增加引用计数
    }

    shared_ptr(shared_ptr&& __r) _NOEXCEPT	// 移动构造函数
        : __ptr_(__r.__ptr_), __cntrl_(__r.__cntrl_)
    {
        __r.__ptr_ = nullptr;
        __r.__cntrl_ = nullptr;
    }
    
	~shared_ptr()	// 析构函数
    {
        if (__cntrl_)
            __cntrl_->__release_shared(); // 释放内存
    }
......
	shared_ptr<_Tp>& operator=(const shared_ptr& __r) _NOEXCEPT	// 赋值运算
    {
        shared_ptr(__r).swap(*this);
        return *this;
    }
......
};

从传入堆内存指针的构造函数不难看出,与引用计数相关的对象指针__cntrl_在此处通过new申请堆内存来保存,而将一个share_ptr对象复制给另一个share_ptr对象时,除了直接对其__ptr___cntrl_赋值,还会执行__add_shared()方法,从方法的名字就能看出这里边一定是增加了引用计数。

与引用计数相关的类__shared_weak_count__shared_count的子类,__shared_weak_count__add_shared()方法实际上就是调用__shared_count__add_shared()

void __add_shared() _NOEXCEPT {
	__shared_count::__add_shared();
}

该方法的底层实际上是使用原子操作来增加计数值:

void __shared_count::__add_shared() noexcept
{
    __libcpp_atomic_refcount_increment(__shared_owners_);	// ↓见下方函数
}

template <class _Tp>
inline _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);	// 原子操作 +1
#else
    return __t += 1;
#endif
}

而在重载的赋值运算符函数中,则是通过shared_ptr(__r).swap(*this);的方法来进行复制操作,这里实际上利用了复制构造函数将引用计数加1,然后再通过swap()完成赋值。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值