简单的shared_ptr实现

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了简单的shared_ptr实现相关的知识,希望对你有一定的参考价值。

RT,代码参考了STL中shard_ptr的实现,基本原理是引用计数,利用Ref_cnt类来管理内存,在shared_ptr创建时创建,此后shared_ptr仅是在拷贝复制析构的过程中对引用进行修改,个人觉得比较有意思的一个地方在于通过对Ref_cnt类多态的应用使得shared_ptr无需额外增加模板参数这个想法(我原来想利用默认模板参数的方法感觉既不灵活又麻烦)。

#ifndef _TSHARED_PTR_
#define _TSHARED_PTR_
#include <cstdlib>
#ifdef _N_C11
#define nullptr 0
#endif
#include <cstdlib>
namespace Tsp{
    class Ref_cnt_base{
    public:
        void decRef(){
            if (--_cnt == 0){
                this->_Destroy();
                this->_Delete_this();
            }
        }
        inline void incRef(){ _cnt++; }
        inline size_t _use_cnt(){ return _cnt; }
        Ref_cnt_base() :_cnt(1){}
#ifndef _N_C11
        ~Ref_cnt_base() = default;
#endif
    protected:
        virtual void _Destroy() = 0;
        virtual void _Delete_this() = 0;
        size_t _cnt;
    };

    template<typename T>
    class Ref_cnt :public Ref_cnt_base{
    public:
#ifndef _N_C11
        Ref_cnt() = delete;
#endif
        Ref_cnt(T*p) : Ref_cnt_base(), _ptr(p){}
#ifndef _N_C11    
        ~Ref_cnt() = default;
#endif
    private:
#ifdef _N_C11
        void _Destroy(){
            delete _ptr;
        }
        void _Delete_this(){
            delete this;
        }
#endif
#ifndef _N_C11
        void _Destroy()override{
            delete _ptr;
        }
        void _Delete_this()override{
            delete this;
        }
#endif
        T *_ptr;
    };

    template<typename T, typename D>
    class Ref_cnt_del :public Ref_cnt_base{
    public:
#ifndef _N_C11
        Ref_cnt_del() = delete;
#endif
        Ref_cnt_del(T*p, D d) :Ref_cnt_base(), _ptr(p), deleter(d){}
#ifndef _N_C11
        ~Ref_cnt_del() = default;
#endif
    private:
#ifdef _N_C11
        void _Destroy(){
            deleter(_ptr);
        }
        void _Delete_this(){
            delete this;
        }
#endif
#ifndef _N_C11
        void _Destroy()override{
            deleter(_ptr);
        }
        void _Delete_this()override{
            delete this;
        }
#endif
        T* _ptr;
        D deleter;
    };

    template<typename T>
    class Tshared_ptr{
    public:
        Tshared_ptr() :_ptr(nullptr), _rep(nullptr){}
        explicit Tshared_ptr(T *p) : _ptr(p), _rep(new Ref_cnt<T>(p)){}
        Tshared_ptr(const Tshared_ptr<T>&r) :_ptr(nullptr), _rep(nullptr){
            if (r._rep != nullptr)
                r._rep->incRef();
            _rep = r._rep;
            _ptr = r._ptr;
        }
        //should add a right value ref
        template<typename Dp>
        Tshared_ptr(T* p, Dp d) : _ptr(p), _rep(new Ref_cnt_del<T, Dp>(p, d)){}
        template<typename Dp>
        Tshared_ptr(const Tshared_ptr<T>&r, Dp d) : _ptr(r._ptr),
            _rep(new Ref_cnt_del<T,Dp>(r._ptr,d)){
            this->_rep->incRef();
        }
        virtual ~Tshared_ptr(){
            if (_rep != nullptr)
                _rep->decRef();
        }
        static void swap(Tshared_ptr<T>&p, Tshared_ptr<T>&q){
            Tshared_ptr<T> tmp(p);
            p = q;
            q = tmp;
        }
        void swap(Tshared_ptr<T>&p){
            Tshared_ptr<T> tmp(p);
            p = *this;
            *this = tmp;
        }
        inline size_t use_count()const{
            return _rep ? _rep->_use_cnt() : 0;
        }
        inline bool isUnique_ptr(){
            return use_count() == 1;
        }

        T* get()const{
            return _ptr;
        }
        void reset(){
            _rep->decRef();
            _ptr = nullptr;
            _rep = nullptr;
        }
        template<typename D>
        void reset(Tshared_ptr<T> &p, D d){
            _ptr = p->_ptr;
            _rep = new Ref_cnt_del<T, D>(_ptr, d);
            p._rep->incRef();
        }
        bool operator == (const Tshared_ptr<T> &r)const{
            return _rep == r._rep;
        }
        bool operator != (const Tshared_ptr<T> &r)const{
            return !(*this == r);
        }
        Tshared_ptr<T>& operator = (const Tshared_ptr<T>&r){
            if (r._rep != nullptr)
                r._rep->incRef();
            if (_rep != nullptr)
                _rep->decRef();
            _rep = r._rep;
            _ptr = r._ptr;
            return *this;
        }
#ifndef _N_C11
        explicit
#endif
            operator bool() const{
            return _ptr != nullptr;
        }
        T& operator* ()const{
            return *_ptr;
        }
        T* operator ->()const{
            return _ptr;
        }
    private:
        T* _ptr;
        Ref_cnt_base* _rep;
    };
    template<typename T>
    Tshared_ptr<T> make_Tshared_pointer(T*p){
        return Tshared_ptr<T>(p);
    }
}
#endif

 

以上是关于简单的shared_ptr实现的主要内容,如果未能解决你的问题,请参考以下文章

实现一个简单的shared_ptr

shared_ptr智能指针模板类的简单实现(c++11)

智能指针基本原理,简单实现,常见问题

代码片段 - Golang 实现简单的 Web 服务器

shared_ptr智能指针模板类的简单实现(c++11)

如何修改shared