• C++ 之实现自己的 shared_ptr


                /*shared_ptr.h 文件*/
    /*********************************************************
        > File Name: shared_ptr.h
        > Author: Liu Shengxi 
        > Mail: 13689209566@163.com
        > Created Time: 2018年06月05日 星期二 15时35分48秒
     *****************************************************/
    
    #ifndef _SHARED_PTR_H
    #define _SHARED_PTR_H
    
    template<typename> class shared_ptr ;
    
    template< class T >
    void swap( shared_ptr<T>& lhs, shared_ptr<T>& rhs ) noexcept 
    {
        std::cout << "swap out object  " << std::endl ;
        lhs.swap(rhs);
    }
    
    template<typename T>
    class shared_ptr {
        using DelFuncPtr = void (*)(T*) ;
    
    public:
        shared_ptr():m_ptr(nullptr),
        count_ptr( new size_t(0)),del(nullptr)
        {
        }
        explicit shared_ptr(T *ptr ,DelFuncPtr temp = nullptr ):
        m_ptr(ptr),count_ptr(new size_t(1)), del(temp )
        { 
        }
        //拷贝构造函数
        shared_ptr(const shared_ptr &hp):
        m_ptr(hp.m_ptr),count_ptr(hp.count_ptr),del(hp.del)
        { 
            ++(*count_ptr) ; //引用计数加1 
        }
        //拷贝赋值运算符 
        shared_ptr& operator=( shared_ptr &rhs){
            swap(*this,rhs);
            return *this;
        }
        //析构函数
        ~shared_ptr(){
            --(*count_ptr);
            if((*count_ptr) == 0 ){
                del ? del(m_ptr):
                    delete m_ptr;
                    delete count_ptr  ;
            }
            m_ptr = nullptr ;
            count_ptr =nullptr ;
        }
        size_t use_count(){ return (*count_ptr);}
        T& operator*() { return *m_ptr ;}
        T* operator->() { return m_ptr ; }
    
        void swap(shared_ptr &hp){
            std::cout << "swap in object " << std::endl ;
            using std::swap ;
            swap(m_ptr,hp.m_ptr);
            swap(count_ptr,hp.count_ptr);
            swap(del,hp.del);
        }
        void reset( ){
            if((*count_ptr) == 1) {
                delete m_ptr;
                delete count_ptr ;
                m_ptr = nullptr ;
                count_ptr =nullptr ;
            }
        }
        void reset( T *hp ,DelFuncPtr del = nullptr ){
            shared_ptr temp(hp,del);
            swap(temp);
        }
    private:
        T* m_ptr = nullptr ;
        size_t* count_ptr = nullptr ;
        //思考一下为什么是size_t*,而不是 size_t ? ?
        DelFuncPtr del = nullptr ; //自定义的删除器
    };
    #endif
                        /*main.cpp 文件*/
    /*************************************************************************
        > File Name: main.cpp
        > Author: Liu Shengxi 
        > Mail: 13689209566@163.com
        > Created Time: 2018年06月05日 星期二 15时39分58秒
     ************************************************************************/
    
    #include <iostream>
    #include"shared_ptr.h"
    using namespace std ;
    struct Foo {
        Foo() { std::cout << "Foo()
    "; }
        ~Foo() { std::cout << "~Foo()
    "; }
        Foo(const Foo&) { std::cout << "Foo copy ctor
    "; }
        Foo(Foo&&) { std::cout << "Foo move ctor
    "; }
    };
    
    struct Fooo {
        Fooo(int n = 0) noexcept : bar(n) { std::cout << "Fooo: constructor, bar = " << bar << '
    '; }
        ~Fooo() { std::cout << "Fooo: destructor, bar = " << bar << '
    '; }
        int GetBar() const noexcept { return bar; }
    
    private:
        int bar;
    };
    
    struct D {
        void bar() { std::cout << "Call deleter D::bar()...
    "; }
        void operator()(Foo* p) const
        {
            std::cout << "Call delete from function object...
    ";
            delete p;
        }
    };
    int main()
    {
    std::cout << "shared_ptr constructor with no managed object
    ";
        {
            shared_ptr<Foo> sh1;
        }
    
        std::cout << "shared_ptr constructor with object and test swap 
    ";
        {
            shared_ptr<Foo> sh2(new Foo);
            std::cout << sh2.use_count() << '
    ';//1
            shared_ptr<Foo> sh3(sh2);
            std::cout << sh3.use_count() << '
    ';// 2
    
            shared_ptr<int> sh4(new int(4444)) ;
            shared_ptr<int> sh5(new int(5555)) ; // test swap()  
            sh4.swap(sh5);
            cout << "sh4 == "  << *sh4 << "
    sh5 == " << *sh5 << endl ; // 5555 4444 
            swap(sh4,sh5);
            cout << "sh4 == "  << *sh4 << "
    sh5 == " << *sh5 << endl ;  //4444  5555
        }
    
        std::cout << "shared_ptr constructor with deleter
    ";
        {
            shared_ptr<Foo> sh5(new Foo, [](Foo* p) {
                std::cout << "Call delete from lambda...
    ";
                delete p;
            });
        }
    
        {
            shared_ptr<Fooo> sptr(new Fooo(111)) ;
            std::cout << "The first Fooo's bar is " << sptr->GetBar() << "
    "; // 111  
            sptr.reset(new Fooo); //先搞一个新的出来,然后干掉原来的,避免自赋值
            std::cout << "The second Fooo's bar is " << sptr->GetBar() << "
    "; // 0 
        }
    }

    运行结果:
    这里写图片描述

    总结:

    1. 什么是size_t 类型
      它是一个与机器相关的unsigned类型,其大小足以保证存储内存中对象的大小。一般用作下标类型 。
    2. 为什么是size_t*,而不是 size_t ? ?

    因为你要定义的是行为像指针的类而不是像值的类,在多个指针共同指向同一个对象时,只需要拷贝指针,利用指针让它引用计数加一就可以了。如果一个指针被析构时,也是通过指针让引用计数减一即可。

    如果为size_t类型的成员变量,在多个shared_ptr对象指向同一资源时,其中一个shared_ptr对象析构了count_ptr = count_ptr -1,但是不会影响到其他shared_ptr对象。所以使用size_t* 来达到多个shared_ptr对象指向同一资源的能够共享count_ptr 的目的。

    3 . 另外注意删除器的书写方式和成员函数swap与友元函数swap的书写即可

  • 相关阅读:
    C#打造51CTO自动签到服务领取无忧币之开篇
    Windows8开发实战之文本布局
    设计模式之抽像工厂
    PDM只显示表名称不显示列表名称
    JS 判断中英文字符长度
    C#操作剪贴板实现复制粘贴
    Chrome控制台设置浏览器Cookie
    通过Mysql查询分析器 建库建表语句
    推荐两个VS开发工具插件
    C#经典机试题(猫叫)
  • 原文地址:https://www.cnblogs.com/Tattoo-Welkin/p/10335289.html
Copyright © 2020-2023  润新知