智能指针简单实现

//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 第五版 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值