/*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()\n"; }
    ~Foo() { std::cout << "~Foo()\n"; }
    Foo(const Foo&) { std::cout << "Foo copy ctor\n"; }
    Foo(Foo&&) { std::cout << "Foo move ctor\n"; }
};

struct Fooo {
    Fooo(int n = 0) noexcept : bar(n) { std::cout << "Fooo: constructor, bar = " << bar << '\n'; }
    ~Fooo() { std::cout << "Fooo: destructor, bar = " << bar << '\n'; }
    int GetBar() const noexcept { return bar; }

private:
    int bar;
};

struct D {
    void bar() { std::cout << "Call deleter D::bar()...\n"; }
    void operator()(Foo* p) const
    {
        std::cout << "Call delete from function object...\n";
        delete p;
    }
};
int main()
{
std::cout << "shared_ptr constructor with no managed object\n";
    {
        shared_ptr<Foo> sh1;
    }

    std::cout << "shared_ptr constructor with object and test swap \n";
    {
        shared_ptr<Foo> sh2(new Foo);
        std::cout << sh2.use_count() << '\n';//1
        shared_ptr<Foo> sh3(sh2);
        std::cout << sh3.use_count() << '\n';// 2

        shared_ptr<int> sh4(new int(4444)) ;
        shared_ptr<int> sh5(new int(5555)) ; // test swap()  
        sh4.swap(sh5);
        cout << "sh4 == "  << *sh4 << "\nsh5 == " << *sh5 << endl ; // 5555 4444 
        swap(sh4,sh5);
        cout << "sh4 == "  << *sh4 << "\nsh5 == " << *sh5 << endl ;  //4444  5555
    }

    std::cout << "shared_ptr constructor with deleter\n";
    {
        shared_ptr<Foo> sh5(new Foo, [](Foo* p) {
            std::cout << "Call delete from lambda...\n";
            delete p;
        });
    }

    {
        shared_ptr<Fooo> sptr(new Fooo(111)) ;
        std::cout << "The first Fooo's bar is " << sptr->GetBar() << "\n"; // 111  
        sptr.reset(new Fooo); //先搞一个新的出来,然后干掉原来的,避免自赋值
        std::cout << "The second Fooo's bar is " << sptr->GetBar() << "\n"; // 0 
    }
}

运行结果:
C++ 之实现自己的 shared_ptr

总结:

  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的书写即可

相关文章: