智能指针简单实现

来源:互联网 发布:mac 4k 字体太小 编辑:程序博客网 时间:2024/05/16 10:37

//SmartPointer,h

#ifndef _SMARTPOINTER_H_#define _SMARTPOINTER_H_namespace practice{template <typename T>class pointer{ protected:    T *m_ptr;public:      explicit pointer(T *ptr = nullptr) noexcept : m_ptr(ptr)      {      }      pointer(const pointer<T>& obj) noexcept : m_ptr(obj.m_ptr)      {      }      operator bool () const      {          return nullptr != m_ptr;      }      bool operator ! () const      {          return nullptr == m_ptr;      }      T& operator *()      {          return *m_ptr;      }      T *operator -> ()      {          return m_ptr;      }      T& operator *() const      {          return *m_ptr;      }      T *operator -> () const      {          return m_ptr;      }      T *get()      {          return m_ptr;      }      bool is_null() const      {          return nullptr == m_ptr;      }      virtual ~pointer() noexcept      {      }};template <typename T>class unique_ptr : public pointer<T>{protected:    void set_null(const unique_ptr<T>& obj)    {        const_cast< unique_ptr<T>& >(obj).m_ptr = nullptr;    }public:    explicit unique_ptr(T *ptr = nullptr ) noexcept : pointer<T>(ptr)    {    }    unique_ptr(const unique_ptr<T>& obj) noexcept :  pointer<T>(obj)    {         set_null(obj);    }    unique_ptr<T>& operator = (const unique_ptr<T>& obj)    {        if( this != &obj )        {            reset(obj.m_ptr);            set_null(obj);        }        return *this;    }    T *take()    {        T *tmp = this->m_ptr;        this->m_ptr = nullptr;        return tmp;    }    void swap(unique_ptr<T>& obj)    {        T *tmp = obj.m_ptr;        obj.m_ptr = this->m_ptr;        this->m_ptr = tmp;    }    void reset(T *ptr = nullptr)    {        delete this->m_ptr;        this->m_ptr = ptr;    }    ~unique_ptr() noexcept    {        reset(nullptr);    }};template <typename T>class shared_ptr : public pointer<T>{protected:    unsigned *m_count;    void increase_count(const shared_ptr<T>& obj)    {        if( nullptr != obj.m_count )        {          ++(*const_cast<shared_ptr<T>& >(obj).m_count);        }        this->m_count = obj.m_count;    }    void decrease_count()    {        if( (nullptr != this->m_count) && (0 == --(*this->m_count)) )        {            delete this->m_ptr;            delete this->m_count;        }    }public:    explicit shared_ptr( T *ptr = nullptr) noexcept : pointer<T>(ptr)    {        if( nullptr != ptr )        {            this->m_count = new unsigned(1);        }        else        {            this->m_count = nullptr;        }    }    shared_ptr(const shared_ptr<T>& obj) noexcept : pointer<T>(obj)    {        increase_count(obj);    }    shared_ptr<T>& operator = (const shared_ptr<T>& obj)    {        if( this != &obj )        {            decrease_count();            increase_count(obj);            this->m_ptr = obj.m_ptr;        }        return *this;    }    bool unique()    {        return 1 == *this->m_count;    }    unsigned use_count()    {        return *this->m_count;    }    ~shared_ptr() noexcept    {        decrease_count();    }};}#endif // _SMARTPOINTER_H_



//main.cpp

#include <iostream>#include "smartpointer.h"using namespace std;class test{ public:    void print()    {        cout << "test" << endl;    }};void test_unique(){    practice::unique_ptr<int> p(new int(10));    if( p )    {        cout << "if( p )" << endl;    }    practice::unique_ptr<int> p2(p);    if( !p )    {        cout << "if( !p )" << endl;    }    p = p2;    if( p2.is_null() )    {        cout << "p2.is_null()" << endl;    }    p2.swap(p);    if( nullptr != p2.get() )    {        cout << "nullptr != p2.get()" << endl;    }    cout << "*p2 = " << *p2 << endl;    int *t = p2.take();    cout << "*t = " << *t << endl;    delete t;    p2.reset(new int(0));    cout << "*p2 = " << *p2 << endl;    practice::unique_ptr<test> pt(new test);    pt->print();}void test_share(){    practice::shared_ptr<int> p(new int(100));    if( p )    {        cout << "if( p )" << endl;    }    if( false == !p )    {        cout << "false == !p" << endl;    }    practice::shared_ptr<int> p2(p);    if( 2 == p.use_count() )    {        cout << "2 == p.use_count()" << endl;    }    p = p2;    practice::shared_ptr<int> p3(new int(1));    p2 = p3;    if( p.unique() )    {        cout << "p.unique()" << endl;    }    *p = 10;    cout << "*p = " << *p << endl;    cout <<"* p3.get() = " << * p3.get() << endl;     practice::shared_ptr<test> p4(new test);     p4->print();}int main(){    test_unique();    test_share();        return 0;}



//本来想加上删除器的,无奈,模板暂时没有好的方法使模板实参个数与构造函数实参个数一致,按照对标准库中的智能指针的测试来看,拿std::uniq_ptr来说:

std::uniq_ptr的两个模板参数,第一个为内部管理的指针指向的对象类型,第二个参数为删除器类型,虽然说第二个模板参数可以是默认删除器,但只要为模板类提供了删除器类型,就必须使用两个实参去调用构造函数,使用一个实参调用构造函数编译器报错,同样的,如果使用默认模板删除器,必须使用一个实参去调用构造函数,使用两个实参编译器报错。如 std::uniq_ptr<int, void(*)(int *)> p(&a)与std::uniq_ptr<int> p2(&a, fun)编译器应该报错,因为模板实参个数与构造函数实参个数不一致,std::uniq_ptr<int, void(*)(int *)> p(&a, func)与std::uniq_ptr<int> p2(&a)编译器不会报错,但是我目前不能做到这一点。


删除器是一个可调用对象,其参数为智能指针内部封装的原生指针,使用默认删除器的情况下,智能指着的析构函数被调用时,删除器其会对原生指针进行释放操作,delete (p),如果传入了自定义的删除器,将会是deleter(p)


参考:C++ Primer 第五版 
原创粉丝点击