Bootstrap

C++(18)——智能指针unique_ptr

简介

unique_ptr 是 C++ 11 提供的用于防止内存泄漏的智能指针中的一种实现,独享被管理对象指针所有权的智能指针。unique_ptr对象包装一个原始指针,并负责其生命周期。当该对象被销毁时,会在其析构函数中删除关联的原始指针。

unique_ptr对象始终是关联的原始指针的唯一所有者,我们无法复制unique_ptr对象,它只能移动。

首先我们利用STL提供的unique_ptr管理对象时,不能完成下面框出的操作:
在这里插入图片描述

上述操作受限与否的原理是什么?和之前一样,我们模仿源码的逻辑,仿写unique_ptr,看看unique_ptr的实现原理:

先来实现一下unqiue_ptr的默认删除器
在这里插入图片描述
由于每个unique_ptr对象都是原始指针的唯一所有者,因此在其析构函数中它直接删除关联的指针,不需要任何参考计数。

//泛化模板类
template<class _Ty>
class Mydeletor
{
    Mydeletor() = default;
    void operator()(_Ty *ptr)const
    {
        if(ptr != nullptr)
        {
            delete ptr;
        }
    }
};

//部分特化
template<class _Ty>
class Mydeletor<_Ty[]>
{
    Mydeletor() = default;
    void operator()(_Ty *ptr)const
    {
        if(ptr != nullptr)
        {
            delete[] ptr;
        }
    }
};

继续完成unqiue_ptr的设计

template<class _Ty,class _Dx = Mydeletor<_Ty>>//给出一个删除单个对象的删除器
class my_unique_ptr
{
//C11新写法
using pointer = _Ty*;    //     typedef _Ty pointer;
using element_type = _Ty;//     typedef _Ty element_type;
using delete_type = _Dx; //     typedef _Dx delete_type;
private:
    _Ty* _Ptr;
    _Dx _myDeletor;
public:
    my_unique_ptr(const my_unique_ptr &) = delete;
    my_unique_ptr & operator=(const my_unique_ptr &) = delete;

    my_unique_ptr(pointer _p = nullptr):_Ptr(_p){}
    ~my_unique_ptr()
    {
        if(_Ptr != nullptr)
        {
            _myDeletor(_Ptr);//对象()——>调动仿函数
            _Ptr = nullptr;
        }
    }

    //移动构造
    my_unique_ptr(my_unique_ptr && _Y)
    {
        _Ptr = _Y._Ptr;
        _Y._Ptr = nullptr;
    }

    //移动赋值
    my_unique_ptr & operator=(my_unique_ptr && _Y)
    {
        if(this == &_Y)return *this;

        reset(_Y.release());
        //if(_Ptr != nullptr)
        //{
        //    _myDeletor(_Ptr);
        //}
        //_Ptr = _Y._Ptr;
        //_Y._Ptr = nullptr;
        return *this;
    }

    //返回删除器对象
    _Dx & get_deletor() 
    {
        return _myDeletor;
    }

    const _Dx & get_deletor() const 
    {
        return _myDeletor;
    }

    //解引用指向被管理对象的指针
    _Ty & operator*()const
     {
         return *_Ptr;
     }
    pointer operator->()const
    {
        return _Ptr;//&**this
    }
    //返回指向管理对象的指针
    pointer get() const
    {
        return _Ptr;
    }

    //测试当前_Ptr指向是否为nullptr
    operator bool() const//强转bool
    {
        return _Ptr != nullptr;
    }
    //my_unqiue_ptr<int> op;
    //if(op){}//——>if(op.operator bool()){}

    pointer release()
    {
        _Ty *old = _Ptr;
        _Ptr = nullptr;
        return old;
    }

    void reset(pointer _P = nullptr)
    {
        pointer old = _Ptr;
        _Ptr = _P;
        if(old != nullptr)
        {
            _myDeletor(old);//get_deletor(old);
        }
    }

    void Swap(my_unique_ptr _Y)
    {
        std::swap(_Ptr,_Y.Ptr);
        std::swap(_myDeletor,_Y._myDeletor);
    }
};

//部分特化:处理数组
class my_unique_ptr<_Ty[],_Dx>
{
//C11新写法
using pointer = _Ty*;    //     typedef _Ty pointer;
using element_type = _Ty;//     typedef _Ty element_type;
using delete_type = _Dx; //     typedef _Dx delete_type;
private:
    _Ty* _Ptr;
    _Dx _myDeletor;
public:
    my_unique_ptr(const my_unique_ptr &) = delete;
    my_unique_ptr & operator=(const my_unique_ptr &) = delete;

    my_unique_ptr(pointer _p = nullptr):_Ptr(_p){}
    ~my_unique_ptr()
    {
        if(_Ptr != nullptr)
        {
            _myDeletor(_Ptr);//对象()——>调动仿函数
            _Ptr = nullptr;
        }
    }

    //移动构造
    my_unique_ptr(my_unique_ptr && _Y)
    {
        _Ptr = _Y._Ptr;
        _Y._Ptr = nullptr;
    }

    //移动赋值
    my_unique_ptr & operator=(my_unique_ptr && _Y)
    {
        if(this == &_Y)return *this;

        reset(_Y.release());
        //if(_Ptr != nullptr)
        //{
        //    _myDeletor(_Ptr);
        //}
        //_Ptr = _Y._Ptr;
        //_Y._Ptr = nullptr;
        return *this;
    }

    //返回删除器对象
    _Dx & get_deletor() 
    {
        return _myDeletor;
    }

    const _Dx & get_deletor() const 
    {
        return _myDeletor;
    }

    //解引用指向被管理对象的指针
    _Ty & operator*()const
     {
         return *_Ptr;
     }
    pointer operator->()const
    {
        return _Ptr;//&**this
    }
    //返回指向管理对象的指针
    pointer get() const
    {
        return _Ptr;
    }

    //检查是否有关联的被管理对象
    operator bool() const//强转bool
    {
        return _Ptr != nullptr;
    }
    //my_unqiue_ptr<int> op;
    //if(op){}//——>if(op.operator bool()){}

    pointer release()
    {
        _Ty *old = _Ptr;
        _Ptr = nullptr;
        return old;
    }

    void reset(pointer _P = nullptr)
    {
        pointer old = _Ptr;
        _Ptr = _P;
        if(old != nullptr)
        {
            _myDeletor(old);//get_deletor(old);
        }
    }

    void Swap(my_unique_ptr _Y)
    {
        std::swap(_Ptr,_Y.Ptr);
        std::swap(_myDeletor,_Y._myDeletor);
    }

    _Ty & operator[](size_t _Idx) const
    {
        return _Ptr[_Idx];
    }
};

template<class _Ty,class ... _Type>//可变参
my_unique_ptr<_Ty> my_make_unique(_Type&& ... arys)
{
    return my_unique_ptr<_Ty>(new _Ty(_arys...)); 
}

unique_ptr具有->*运算符重载符,因此它可以像普通指针一样使用。
关于unique_ptr的使用,可以参考这一篇博客:
C++ 智能指针 unique_ptr 详解与示例

;