引用计数智能指针

2022-10-10  本文已影响0人  my_passion

1个简单的 引用计数智能指针

本代码取自陈硕的 github 仓库

https://github.com/chenshuo/recipes/blob/master/basic/counted_ptr.h

(1) Ctor: 默认RCSP是空 RCSP: 目标对象和RC 指针均为空 => 还没产生 RC, 而不是 RC = 0

(2) Copy Ctor: 若右侧RCSP的RC指针非空, 则 RC(原子)加1

(3) Move Ctor: 控制权转交, 源 RCSP 2个指针均置空

(4) Assignment: 调 swap(rhs), 交换两者的内容(2个指针) => 若1侧为默认RCSP, 交换后, 另一侧变为默认RCSP

(5) Dtor: 调 reset(), 若 RC 指针非空, 则 RC(原子)减1, 若减为0, 则 delete 目标对象和RC 内存

#pragma once

// A simple reference counted smart pointer.
// make use of GCC atomic builtins and C++ move semantics
template<typename T>
class counted_ptr
{
private:
    T* ptr_;     // 目标对象指针
    int* count_; // RC 动态内存指针

public:
    
    // (1) Ctor: 若 RCSP 所接管的裸指针为空, RC指针置空; 
    //              => `默认 RCSP 是 空 RCSP: 目标对象和RC 指针均为空 => 还没产生 RC, 而不是 RC = 0`
    //           else, RC指针指向新分配的空间, RC初值为1 
    counted_ptr(T* p = nullptr)
        : ptr_(p),
          count_(p ? new int(1) : nullptr)
    { }
    
    // (2) Copy Ctor: 若右侧RCSP的RC指针非空, 则 RC(原子)加1
    counted_ptr(const counted_ptr& rhs) noexcept
        : ptr_(rhs.ptr_),
          count_(rhs.count_)
    {
        if (count_)
          __atomic_fetch_add(count_, 1, __ATOMIC_SEQ_CST);
    }
    
    // (3) Move Ctor: 控制权转交, 源 RCSP 2个指针均置空
    counted_ptr(counted_ptr&& rhs) noexcept
        : ptr_(rhs.ptr_),
          count_(rhs.count_)
    {
        rhs.ptr_ = nullptr;
        rhs.count_ = nullptr;
    }
    
    // (4) Assignment: 调 swap(rhs)
    counted_ptr& 
    operator=(counted_ptr rhs)
    {
        swap(rhs);
        return *this;
    }
    
    // 交换两者的内容(2个指针) => `若1侧为默认RCSP, 交换后, 另一侧变为默认RCSP`
    void swap(counted_ptr& rhs) noexcept
    {
        T* tp = ptr_;
        ptr_ = rhs.ptr_;
        rhs.ptr_ = tp;

        int* tc = count_;
        count_ = rhs.count_;
        rhs.count_ = tc;
    }
    
    // (5) Dtor: 调 reset() 
    ~counted_ptr()
    {
        reset();
    }
    
    // 若 RC 指针非空, 则 RC(原子)减1, 若减为0, 则 delete 目标对象和RC 内存
    void reset()
    {
        static_assert(sizeof(T) > 0, "T must be complete type");
        if (count_)
        {
            if (__atomic_sub_fetch(count_, 1, __ATOMIC_SEQ_CST) == 0)
            {
                delete ptr_;
                delete count_;
            }
            ptr_ = nullptr;
            count_ = nullptr;
        }
    }
    
    // (6) 获取内部裸指针 
    T* 
    get() const noexcept
    {
        return ptr_;
    }
    
    // (7) 获取内部 RC: (原子)load
    int 
    use_count() const noexcept
    {
        return count_ ? __atomic_load_n(count_, __ATOMIC_SEQ_CST) : 0;
    }
    
    T* 
    operator->() const noexcept
    {
        return ptr_;
    }

    T& 
    operator*() const noexcept
    {
        return *ptr_;
    }
};
上一篇 下一篇

猜你喜欢

热点阅读