简单的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
时间: 2024-08-06 18:25:51

简单的shared_ptr实现的相关文章

实现一个简单的shared_ptr

template <typename T> class shared_ptr { public: explicit shared_ptr (T *ptr): mPtr(ptr), cnt(new int(1)){} shared_ptr(const shared_ptr& rhs): mPtr(rhs.mPtr), cnt(rhs.cnt){ ++*cnt; } shared_ptr& operator = (const shared_ptr&); ~shared_pt

第 13 章

13.1 [出题思路] 理解拷贝构造函数的基本概念. [解答] 如果构造函数的第一个参数是自身类类型的引用,且所有其他参数(如果有的话)都有默认值,则此构造函数是拷贝构造函数.拷贝构造函数在以下几种情况下会被使用: 拷贝初始化(用 = 定义变量). 将一个对象作为实参传递给非引用类型的形参. 一个返回类型为非引用类型的函数返回一个对象. 用花括号列表初始化一个数组中的元素或一个聚合类中的成员. 初始化标准库容器或调用其 insert/push 操作时,容器会对其元素进行拷贝初始化. 13.2 [

shared_ptr的简单实现

前面讲到auto_ptr有个很大的缺陷就是所有权的转移,就是一个对象的内存块只能被一个智能指针对象所拥有.但我们有些时候希望共用那个内存块.于是C++ 11标准中有了shared_ptr这样的智能指针,顾名思义,有个shared表明共享嘛.所以shared_ptr类型的智能指针可以做为STL容器的元素 下面我们来瞧瞧shared_ptr具体是咋实现的.相较auto_ptr有下面几个不同的地方: 1.引进了一个计数器shared_count,用来表示当前有多少个智能指针对象共享指针指向的内存块 2

智能指针的原理和简单实现

什么是智能指针? 智能指针实质上是一个类,定义一个类来封装资源的分配和释放.这个类的构造函数中传入一个指针,完成资源的分配和初始化.在析构函数中释放传入的该指针,完成资源的释放. 为什么要用智能指针? 智能指针就是智能,自动化的管理指针所指向的动态资源. 例如以下情况:代码中经常会忘记释放动态开辟的内存资源,导致内存泄露. // case1 void Test2() {  int* p1 = new int(2);  bool isEnd = true;  //...  if (isEnd)  

C++智能指针简单剖析

导读 最近在补看<C++ Primer Plus>第六版,这的确是本好书,其中关于智能指针的章节解析的非常清晰,一解我以前的多处困惑.C++面试过程中,很多面试官都喜欢问智能指针相关的问题,比如你知道哪些智能指针?shared_ptr的设计原理是什么?如果让你自己设计一个智能指针,你如何完成?等等--.而且在看开源的C++项目时,也能随处看到智能指针的影子.这说明智能指针不仅是面试官爱问的题材,更是非常有实用价值. 下面是我在看智能指针时所做的笔记,希望能够解决你对智能指针的一些困扰. 目录

C++智能指针剖析(下)boost::shared_ptr&amp;其他

1. boost::shared_ptr 前面我已经讲解了两个比较简单的智能指针,它们都有各自的优缺点.由于 boost::scoped_ptr 独享所有权,当我们真真需要复制智能指针时,需求便满足不了了,如此我们再引入一个智能指针,专门用于处理复制,参数传递的情况,这便是如下的boost::shared_ptr. boost::shared_ptr 属于 boost 库,定义在 namespace boost 中,包含头文件#include<boost/smart_ptr.hpp> 便可以使

智能指针 std::auto_ptr 和 shared_ptr

需要注意: auto_ptr 类可以用于管理由 new 分配的单个对象,但是无法管理动态分配的数组(我们通常不会使用数组,而是使用 vector 代替数组).auto_ptr 在拷贝和赋值的时候有不寻常的行为,因此 auto_ptrs 不能被保存在 stl 的容器中.当 auto_ptr 离开了自己的作用域或者被销毁,由 auto_ptr 管理的对象也会被销毁. 使用std::auto_ptr需要的头文件: #include <memory> // 示例 1(b): 安全代码, 使用了auto

使用C++实现一套简单的状态机模型——实例

一般来说,"状态机"是一种表达状态转换变换逻辑的方法.曾经有人和我讨论过为什么不直接用ifelse,而要使用"状态机"去实现一些逻辑,认为使用"状态机"是一种炫技的表现.然而对于大型复杂逻辑的变化和跳转,使用ifelse将带来代码难以阅读等弊端.其实ifelse也是一种状态机实现的方式. 之前我们有个业务和操作系统有着强烈的关联,而我们希望比较清晰地描述整个业务中各个子业务的过程,就引入了状态机描述的方式.可是当时的状态机是使用if else方法

使用C++实现一套简单的状态机模型——原理解析

在上一文中,我们介绍了该状态机模型的使用方法.通过例子,我们发现可以使用该模型快速构建满足基本业务需求的状态机.本文我们将解析该模型的基础代码,以便大家可以根据自己状态机特点进行修改.(转载请指明出于breaksoftware的csdn博客) 该模板库的基础方法实现在之后给出的工程的AutoStateChart.h中,该文件一共215行,其中有16行是辅助调试代码.以上一文中状态机类为例: class CMachine_Download_Run_App : public AutoStateCha