• 共享智能指针shared_ptr的实现


         shared_ptr是一个最像指针的“智能指针”,是boost.smart_ptr库中最有价值、最重要的组成部分,也是最有用的,Boost库的许多组件——甚至还包括其他一些领域的智能指针都使用了shared_ptr,所以它被毫无悬念地收入了C++11标准。

         shared_ptr与scoped_ptr一样包装了new操作符在堆上分配的动态对象,但它实现的是引用计数型的智能指针0,可以被自由地拷贝和赋值,在任意的地方共享它,当没有代码使用(引用计数为0)它时才删除被包装的动态分配的对象。

    shared_ptr也可以安全地放到标准容器中,是在STL容器中存储指针的最标准解法。

    实现原理

    image

    #include<iostream>
    #include<vld.h>
    using namespace std;
    
    //shared_ptr
    //#define TEST
    class sharend_base
    {
    public:
        sharend_base():use_count(1)
        {
    #ifdef TEST
            cout << "Create sharend_base object." << endl;
    #endif
        }
        virtual void dispose() = 0;//纯虚函数
        virtual void destroy()
        {
            delete this;
        }
        void release()
        {
            if (--use_count == 0)
            {
                dispose();
                destroy();
            }
        }
        void add_uc()
        {
            ++use_count;
        }
        ~sharend_base()
        {
    #ifdef TEST
            cout << "Free sharend_base object." << endl;
    #endif
        }
        long u_count()const
        {
            return use_count;
        }
    private:
        long use_count;
    };
    
    template<typename Y>
    class sharend_conunt_impl:public sharend_base
    {
    public:
        sharend_conunt_impl():pi(nullptr)
        {
    #ifdef TEST
            cout << "Create sharend_conunt_impl object." << endl;
    #endif
        }
        sharend_conunt_impl(Y*p):_pi(p)
        {
    #ifdef TEST
            cout << "Create sharend_conunt_impl object." << endl;
    #endif
        }
        sharend_conunt_impl(sharend_conunt_impl<Y>&p) :_pi(p._pi)
        {
    #ifdef TEST
            cout << "Create sharend_conunt_impl object." << endl;
    #endif
        }
        sharend_conunt_impl& operator=(sharend_conunt_impl&tm)
        {
            _pi = tm._pi;
        }
        ~sharend_conunt_impl()
        {
            _pi=nullptr;
    #ifdef TEST
            cout << "Free sharend_conunt_impl object." << endl;
    #endif
        }
        void destroy()
        {
            delete this;
        }
        void dispose()
        {
            delete _pi;
        }
    private:
        Y*_pi;
    };
    
    class sharend_conunt
    {
    public:
        sharend_conunt():pe()
        {
    #ifdef TEST
            cout << "Create shared_conunt object." << endl;
    #endif
        }
        template <typename V>
        sharend_conunt(V*p):pe(new sharend_conunt_impl<V>(p))
        {
    #ifdef TEST
            cout << "Create shared_conunt object." << endl;
    #endif
        }
        sharend_conunt(sharend_conunt &p):pe(p.pe)
        {
            if (pe)
                pe->add_uc();
    #ifdef TEST
            cout << "Create shared_conunt object." << endl;
    #endif
        }
        ~sharend_conunt()
        {
            if (pe)
                pe->release();
    #ifdef TEST
            cout << "Free shared_conunt object." << endl;
    #endif
        }
        sharend_conunt& operator=(const sharend_conunt&tem)
        {
            if (this != &tem)
            {
                pe = tem.pe;
                if (pe)
                    pe->add_uc();
            }
            return *this;
        }
        long count()const
        {
            return pe->u_count();
        }
    private:
        sharend_base *pe; 
    };
    
    template<typename T>
    class shared_ptr
    {
    public:
        shared_ptr():px(nullptr),pn()
        {
    #ifdef TEST
            cout << "Create shared_ptr object." << endl;
    #endif
        }
        shared_ptr(T*p):px(p),pn(p)
        {
            cout << "Create shared_ptr object." << endl;
        }
        shared_ptr(shared_ptr<T>& r):px(r.px),pn(r.pn)
        {
    #ifdef TEST
            cout << "Create shared_ptr object." << endl;
    #endif
        }
        ~shared_ptr()
        {
    #ifdef TEST
            cout << "Free shared_ptr object." << endl;
    #endif
        }
        void count()const
        {
            cout << "use_count="<< pn.count() << endl;
        }
        typedef shared_ptr<T> this_type;
        shared_ptr& operator=(const shared_ptr &tmp)
        {
            if (this != &tmp)
            {
                px = tmp.px;
                pn = tmp.pn;
            }
            return *this;
        }
        T & operator*()const
        {
            return *px;
        }
        T*operator->()const
        {
            return px;
        }
    private:
        T*px;
        sharend_conunt pn;
    };
    
    主函数:
    
    void main(){        int *ptr = new int(10);
        shared_ptr<int> ps(ptr);
        cout <<*ps<<endl;
        ps.count();
        {
            shared_ptr<int> pt = ps;
            ps.count();
        }
        ps.count();
        shared_ptr<int> pt;
        pt = ps;
        ps.count();}

    小编实现的是只有一些基础功能的,真正的还要看源码。

    这里面要注意的就是sharend_conunt_impl这个类的子类对象要进行自杀,否则会出现内存泄漏。

    下面就是vld.h头文件中的检查内存泄漏问题,这里是没有内存泄漏的所以:

    image

    运行结果:

    image


    ---------------------------------------------------------------------------------------------------------------------------------------------------

             无冥冥之志者,无昭昭之明,无惛惛之事者,无赫赫之功!

  • 相关阅读:
    值初始化-new
    CLI-error
    批量处理
    makefile --文件文档经链接使用
    数据库查询优化
    动态加载数据抓取-Ajax
    requests.post()
    requests.get()参数
    xpath练习(链家二手房案例,百度贴吧图片抓取案例)
    xpath解析.lxml解析库
  • 原文地址:https://www.cnblogs.com/ycw1024/p/11385665.html
Copyright © 2020-2023  润新知