c++-内存管理-shared_ptr等

Shared_ptr

使用引用计数,每一个shared_ptr的拷贝都指向相同的内存。在最后一个shared_ptr析构的时候,内存才被释放。

初始化

std::shared_ptr<int> p(new int(2));

p.reset(new int(1));

获取原始指针

std::shared_ptr<int> ptr(new int(1));

int* p=ptr.get();

指定删除器

void DeleteIntPtr(int* p)

{

     delete P;

}

std::shard_ptr<int> p(new int, DeleteIntPtr);

std::shared_ptr<int> p(new int[10], [](int* p){delete[] p;});

使用shared_ptr注意的问题

1.用一个原始指针初始化多个shared_ptr

2.不要在函数市场中创建shared_ptr

funtion (shared_ptr<int>(new int),g());

3.通过shared_from_this返回this指针。不要将this指针左shared_ptr返回出来,因为this指针本质上是一个裸指针,会导致重复析构。

return shared_ptr<A)(this);xxxxxxxxxxxxxx

应该使用std::enable_shared_from_this<T>,然后基类的成员函数shared_from_this来返回this的shared_ptr

class A:public std::enable_shared_from_this<A>

{

    std::shared_ptr<A> GetSelf(){

         return shared_from_this();

}

}

4.避免重复引用。

class A{

 std::shard_ptr<B> bptr;

}

class B{

std::shard_ptr<A> bp2;

}

unique_ptr独占共享指针

它不允许其他的智能指针共享其内部的指针,不允许通过赋值将一个unique_ptr赋值给另外一个unique_ptr.

可以通过std::move来把指针交给其他unique_ptr.

unique_ptr指定删除器,需要指定删除器的类型。

std::unique_ptr<int,void(*)(int*)> ptr(niew int(1), [](int* p){delete p});

如果捕获了参数,需要使用如下:

std::unique_ptr<int, std::function<void(int*)>> ptr(niew int(1), [](int* p){delete p});

 

weak_ptr弱引用的智能指针

用来监视shard_ptr,不会使引用计数加1,不管理shared_ptr的内部指针。

1.通过use_count获取观察资源的引用计数

shared_ptr<int> sp(new int(10));

weak_ptr<int> wp(sp);

cout<<wp.use_count()<<endl;

2.通过expired()方法来判断观察到的资源是否已经被释放了

shared_ptr<int> sp(new int(10);

weak_ptr<int> wp(sp);

if(wp.expired())

3.通过lock来获取监控的shared_ptr

std::weak_ptr<int> gw;

gw.lock();

4.weak_ptr可以解决相互引用的问题

 

管理三方库:

std::shared_ptr<void> Guard(void* p){

return std::shared_ptr<void> sp(p, [this](void* p){Gethandle()->Release(p);});

}

void* p=Gethandle()->Create();

auto sp=Guard(p);

    // CLASS TEMPLATE _Ptr_base
template<class _Ty>
    class _Ptr_base
    {    // base class for shared_ptr and weak_ptr
public:
    using element_type = remove_extent_t<_Ty>;

    _NODISCARD long use_count() const noexcept
        {    // return use count
        return (_Rep ? _Rep->_Use_count() : 0);
        }

    template<class _Ty2>
        _NODISCARD bool owner_before(const _Ptr_base<_Ty2>& _Right) const noexcept
        {    // compare addresses of manager objects
        return (_Rep < _Right._Rep);
        }

    _Ptr_base(const _Ptr_base&) = delete;
    _Ptr_base& operator=(const _Ptr_base&) = delete;

protected:
    _NODISCARD element_type * get() const noexcept
        {    // return pointer to resource
        return (_Ptr);
        }

    constexpr _Ptr_base() noexcept = default;

    ~_Ptr_base() = default;

    template<class _Ty2>
        void _Move_construct_from(_Ptr_base<_Ty2>&& _Right)
        {    // implement shared_ptr's (converting) move ctor and weak_ptr's move ctor
        _Ptr = _Right._Ptr;
        _Rep = _Right._Rep;

        _Right._Ptr = nullptr;
        _Right._Rep = nullptr;
        }

    template<class _Ty2>
        void _Copy_construct_from(const shared_ptr<_Ty2>& _Other)
        {    // implement shared_ptr's (converting) copy ctor
        if (_Other._Rep)
            {
            _Other._Rep->_Incref();
            }

        _Ptr = _Other._Ptr;
        _Rep = _Other._Rep;
        }

    template<class _Ty2>
        void _Alias_construct_from(const shared_ptr<_Ty2>& _Other, element_type * _Px)
        {    // implement shared_ptr's aliasing ctor
        if (_Other._Rep)
            {
            _Other._Rep->_Incref();
            }

        _Ptr = _Px;
        _Rep = _Other._Rep;
        }

    template<class _Ty0>
        friend class weak_ptr;    // specifically, weak_ptr::lock()

    template<class _Ty2>
        bool _Construct_from_weak(const weak_ptr<_Ty2>& _Other)
        {    // implement shared_ptr's ctor from weak_ptr, and weak_ptr::lock()
        if (_Other._Rep && _Other._Rep->_Incref_nz())
            {
            _Ptr = _Other._Ptr;
            _Rep = _Other._Rep;
            return (true);
            }

        return (false);
        }

    void _Decref()
        {    // decrement reference count
        if (_Rep)
            {
            _Rep->_Decref();
            }
        }

    void _Swap(_Ptr_base& _Right) noexcept
        {    // swap pointers
        _STD swap(_Ptr, _Right._Ptr);
        _STD swap(_Rep, _Right._Rep);
        }

    void _Set_ptr_rep(element_type * _Other_ptr, _Ref_count_base * _Other_rep)
        {    // take new resource
        _Ptr = _Other_ptr;
        _Rep = _Other_rep;
        }

    template<class _Ty2>
        void _Weakly_construct_from(const _Ptr_base<_Ty2>& _Other)
        {    // implement weak_ptr's ctors
        if (_Other._Rep)
            {
            _Other._Rep->_Incwref();
            }

        _Ptr = _Other._Ptr;
        _Rep = _Other._Rep;
        }

    void _Decwref()
        {    // decrement weak reference count
        if (_Rep)
            {
            _Rep->_Decwref();
            }
        }

private:
    element_type * _Ptr{nullptr};
    _Ref_count_base * _Rep{nullptr};

    template<class _Ty0>
        friend class _Ptr_base;

#if _HAS_STATIC_RTTI
    template<class _Dx,
        class _Ty0>
        friend _Dx * get_deleter(const shared_ptr<_Ty0>& _Sx) noexcept;
#endif /* _HAS_STATIC_RTTI */
    };

// CLASS TEMPLATE shared_ptr
template<class _Ty>
    class shared_ptr
        : public _Ptr_base<_Ty>
    {    // class for reference counted resource management
private:
    using _Mybase = _Ptr_base<_Ty>;

public:
    using typename _Mybase::element_type;

#if _HAS_CXX17
    using weak_type = weak_ptr<_Ty>;
#endif /* _HAS_CXX17 */

    constexpr shared_ptr() noexcept
        {    // construct empty shared_ptr
        }

    constexpr shared_ptr(nullptr_t) noexcept
        {    // construct empty shared_ptr
        }

    template<class _Ux,
        enable_if_t<conjunction_v<conditional_t<is_array_v<_Ty>, _Can_array_delete<_Ux>, _Can_scalar_delete<_Ux>>,
            _SP_convertible<_Ux, _Ty>>, int> = 0>
        explicit shared_ptr(_Ux * _Px)
        {    // construct shared_ptr object that owns _Px
        _Setp(_Px, is_array<_Ty>{});
        }

    template<class _Ux,
        class _Dx,
        enable_if_t<conjunction_v<is_move_constructible<_Dx>,
            _Can_call_function_object<_Dx&, _Ux *&>,
            _SP_convertible<_Ux, _Ty>>, int> = 0>
        shared_ptr(_Ux * _Px, _Dx _Dt)
        {    // construct with _Px, deleter
        _Setpd(_Px, _STD move(_Dt));
        }

    template<class _Ux,
        class _Dx,
        class _Alloc,
        enable_if_t<conjunction_v<is_move_constructible<_Dx>,
            _Can_call_function_object<_Dx&, _Ux *&>,
            _SP_convertible<_Ux, _Ty>>, int> = 0>
        shared_ptr(_Ux * _Px, _Dx _Dt, _Alloc _Ax)
        {    // construct with _Px, deleter, allocator
        _Setpda(_Px, _STD move(_Dt), _Ax);
        }

    template<class _Dx,
        enable_if_t<conjunction_v<is_move_constructible<_Dx>,
            _Can_call_function_object<_Dx&, nullptr_t&>
        >, int> = 0>
        shared_ptr(nullptr_t, _Dx _Dt)
        {    // construct with nullptr, deleter
        _Setpd(nullptr, _STD move(_Dt));
        }

    template<class _Dx,
        class _Alloc,
        enable_if_t<conjunction_v<is_move_constructible<_Dx>,
            _Can_call_function_object<_Dx&, nullptr_t&>
        >, int> = 0>
        shared_ptr(nullptr_t, _Dx _Dt, _Alloc _Ax)
        {    // construct with nullptr, deleter, allocator
        _Setpda(nullptr, _STD move(_Dt), _Ax);
        }

    template<class _Ty2>
        shared_ptr(const shared_ptr<_Ty2>& _Right, element_type * _Px) noexcept
        {    // construct shared_ptr object that aliases _Right
        this->_Alias_construct_from(_Right, _Px);
        }

    shared_ptr(const shared_ptr& _Other) noexcept
        {    // construct shared_ptr object that owns same resource as _Other
        this->_Copy_construct_from(_Other);
        }

    template<class _Ty2,
        enable_if_t<_SP_pointer_compatible<_Ty2, _Ty>::value, int> = 0>
        shared_ptr(const shared_ptr<_Ty2>& _Other) noexcept
        {    // construct shared_ptr object that owns same resource as _Other
        this->_Copy_construct_from(_Other);
        }

    shared_ptr(shared_ptr&& _Right) noexcept
        {    // construct shared_ptr object that takes resource from _Right
        this->_Move_construct_from(_STD move(_Right));
        }

    template<class _Ty2,
        enable_if_t<_SP_pointer_compatible<_Ty2, _Ty>::value, int> = 0>
        shared_ptr(shared_ptr<_Ty2>&& _Right) noexcept
        {    // construct shared_ptr object that takes resource from _Right
        this->_Move_construct_from(_STD move(_Right));
        }

    template<class _Ty2,
        enable_if_t<_SP_pointer_compatible<_Ty2, _Ty>::value, int> = 0>
        explicit shared_ptr(const weak_ptr<_Ty2>& _Other)
        {    // construct shared_ptr object that owns resource *_Other
        if (!this->_Construct_from_weak(_Other))
            {
            _THROW(bad_weak_ptr{});
            }
        }

 #if _HAS_AUTO_PTR_ETC
    template<class _Ty2,
        enable_if_t<is_convertible_v<_Ty2 *, _Ty *>, int> = 0>
        shared_ptr(auto_ptr<_Ty2>&& _Other)
        {    // construct shared_ptr object that owns *_Other.get()
        _Ty2 * _Px = _Other.get();
        _Set_ptr_rep_and_enable_shared(_Px, new _Ref_count<_Ty2>(_Px));
        _Other.release();
        }
 #endif /* _HAS_AUTO_PTR_ETC */

    template<class _Ux,
        class _Dx,
        enable_if_t<conjunction_v<
            _SP_pointer_compatible<_Ux, _Ty>,
            is_convertible<typename unique_ptr<_Ux, _Dx>::pointer, element_type *>
        >, int> = 0>
        shared_ptr(unique_ptr<_Ux, _Dx>&& _Other)
        {    // construct from unique_ptr
        using _Fancy_t = typename unique_ptr<_Ux, _Dx>::pointer;
        using _Raw_t = typename unique_ptr<_Ux, _Dx>::element_type *;
        using _Deleter_t = conditional_t<is_reference_v<_Dx>, decltype(_STD ref(_Other.get_deleter())), _Dx>;

        const _Fancy_t _Fancy = _Other.get();

        if (_Fancy)
            {
            const _Raw_t _Raw = _Fancy;
            const auto _Rx = new _Ref_count_resource<_Fancy_t, _Deleter_t>(_Fancy, _Other.get_deleter());
            _Set_ptr_rep_and_enable_shared(_Raw, _Rx);
            _Other.release();
            }
        }

    ~shared_ptr() noexcept
        {    // release resource
        this->_Decref();
        }

    shared_ptr& operator=(const shared_ptr& _Right) noexcept
        {    // assign shared ownership of resource owned by _Right
        shared_ptr(_Right).swap(*this);
        return (*this);
        }

    template<class _Ty2>
        shared_ptr& operator=(const shared_ptr<_Ty2>& _Right) noexcept
        {    // assign shared ownership of resource owned by _Right
        shared_ptr(_Right).swap(*this);
        return (*this);
        }

    shared_ptr& operator=(shared_ptr&& _Right) noexcept
        {    // take resource from _Right
        shared_ptr(_STD move(_Right)).swap(*this);
        return (*this);
        }

    template<class _Ty2>
        shared_ptr& operator=(shared_ptr<_Ty2>&& _Right) noexcept
        {    // take resource from _Right
        shared_ptr(_STD move(_Right)).swap(*this);
        return (*this);
        }

 #if _HAS_AUTO_PTR_ETC
    template<class _Ty2>
        shared_ptr& operator=(auto_ptr<_Ty2>&& _Right)
        {    // assign ownership of resource pointed to by _Right
        shared_ptr(_STD move(_Right)).swap(*this);
        return (*this);
        }
 #endif /* _HAS_AUTO_PTR_ETC */

    template<class _Ux,
        class _Dx>
        shared_ptr& operator=(unique_ptr<_Ux, _Dx>&& _Right)
        {    // move from unique_ptr
        shared_ptr(_STD move(_Right)).swap(*this);
        return (*this);
        }

    void swap(shared_ptr& _Other) noexcept
        {    // swap pointers
        this->_Swap(_Other);
        }

    void reset() noexcept
        {    // release resource and convert to empty shared_ptr object
        shared_ptr().swap(*this);
        }

    template<class _Ux>
        void reset(_Ux * _Px)
        {    // release, take ownership of _Px
        shared_ptr(_Px).swap(*this);
        }

    template<class _Ux,
        class _Dx>
        void reset(_Ux * _Px, _Dx _Dt)
        {    // release, take ownership of _Px, with deleter _Dt
        shared_ptr(_Px, _Dt).swap(*this);
        }

    template<class _Ux,
        class _Dx,
        class _Alloc>
        void reset(_Ux * _Px, _Dx _Dt, _Alloc _Ax)
        {    // release, take ownership of _Px, with deleter _Dt, allocator _Ax
        shared_ptr(_Px, _Dt, _Ax).swap(*this);
        }

    using _Mybase::get;

    template<class _Ty2 = _Ty,
        enable_if_t<!disjunction_v<is_array<_Ty2>, is_void<_Ty2>>, int> = 0>
        _NODISCARD _Ty2& operator*() const noexcept
        {    // return reference to resource
        return (*get());
        }

    template<class _Ty2 = _Ty,
        enable_if_t<!is_array_v<_Ty2>, int> = 0>
        _NODISCARD _Ty2 * operator->() const noexcept
        {    // return pointer to resource
        return (get());
        }

    template<class _Ty2 = _Ty,
        class _Elem = element_type,
        enable_if_t<is_array_v<_Ty2>, int> = 0>
        _NODISCARD _Elem& operator[](ptrdiff_t _Idx) const
        {    // subscript
        return (get()[_Idx]);
        }

    _NODISCARD _CXX17_DEPRECATE_SHARED_PTR_UNIQUE bool unique() const noexcept
        {    // return true if no other shared_ptr object owns this resource
        return (this->use_count() == 1);
        }

    explicit operator bool() const noexcept
        {    // test if shared_ptr object owns a resource
        return (get() != nullptr);
        }

private:
    template<class _Ux>
        void _Setp(_Ux * _Px, true_type)
        {    // take ownership of _Px
        _Setpd(_Px, default_delete<_Ux[]>{});
        }

    template<class _Ux>
        void _Setp(_Ux * _Px, false_type)
        {    // take ownership of _Px
        _TRY_BEGIN    // allocate control block and set
        _Set_ptr_rep_and_enable_shared(_Px, new _Ref_count<_Ux>(_Px));
        _CATCH_ALL    // allocation failed, delete resource
        delete _Px;
        _RERAISE;
        _CATCH_END
        }

    template<class _UxptrOrNullptr,
        class _Dx>
        void _Setpd(_UxptrOrNullptr _Px, _Dx _Dt)
        {    // take ownership of _Px, deleter _Dt
        _TRY_BEGIN    // allocate control block and set
        _Set_ptr_rep_and_enable_shared(_Px, new _Ref_count_resource<_UxptrOrNullptr, _Dx>(_Px, _STD move(_Dt)));
        _CATCH_ALL    // allocation failed, delete resource
        _Dt(_Px);
        _RERAISE;
        _CATCH_END
        }

    template<class _UxptrOrNullptr,
        class _Dx,
        class _Alloc>
        void _Setpda(_UxptrOrNullptr _Px, _Dx _Dt, _Alloc _Ax)
        {    // take ownership of _Px, deleter _Dt, allocator _Ax
        using _Refd = _Ref_count_resource_alloc<_UxptrOrNullptr, _Dx, _Alloc>;
        using _Alref_alloc = _Rebind_alloc_t<_Alloc, _Refd>;
        using _Alref_traits = allocator_traits<_Alref_alloc>;
        _Alref_alloc _Alref(_Ax);

        _TRY_BEGIN    // allocate control block and set
        const auto _Pfancy = _Alref_traits::allocate(_Alref, 1);
        _Refd * const _Pref = _Unfancy(_Pfancy);
            _TRY_BEGIN
            _Alref_traits::construct(_Alref, _Pref, _Px, _STD move(_Dt), _Ax);
            _Set_ptr_rep_and_enable_shared(_Px, _Pref);
            _CATCH_ALL
            _Alref_traits::deallocate(_Alref, _Pfancy, 1);
            _RERAISE;
            _CATCH_END
        _CATCH_ALL    // allocation failed, delete resource
        _Dt(_Px);
        _RERAISE;
        _CATCH_END
        }

    template<class _Ty0,
        class... _Types>
        friend shared_ptr<_Ty0> make_shared(_Types&&... _Args);

    template<class _Ty0,
        class _Alloc,
        class... _Types>
        friend shared_ptr<_Ty0> allocate_shared(const _Alloc& _Al_arg, _Types&&... _Args);

    template<class _Ux>
        void _Set_ptr_rep_and_enable_shared(_Ux * _Px, _Ref_count_base * _Rx)
        {    // take ownership of _Px
        this->_Set_ptr_rep(_Px, _Rx);
        _Enable_shared_from_this(*this, _Px);
        }

    void _Set_ptr_rep_and_enable_shared(nullptr_t, _Ref_count_base * _Rx)
        {    // take ownership of nullptr
        this->_Set_ptr_rep(nullptr, _Rx);
        }
    };

#if _HAS_CXX17
template<class _Ty>
    shared_ptr(weak_ptr<_Ty>) -> shared_ptr<_Ty>;

template<class _Ty,
    class _Dx>
    shared_ptr(unique_ptr<_Ty, _Dx>) -> shared_ptr<_Ty>;
#endif /* _HAS_CXX17 */

template<class _Ty1,
    class _Ty2>
    _NODISCARD bool operator==(const shared_ptr<_Ty1>& _Left, const shared_ptr<_Ty2>& _Right) noexcept
    {
    return (_Left.get() == _Right.get());
    }

template<class _Ty1,
    class _Ty2>
    _NODISCARD bool operator!=(const shared_ptr<_Ty1>& _Left, const shared_ptr<_Ty2>& _Right) noexcept
    {
    return (_Left.get() != _Right.get());
    }

template<class _Ty1,
    class _Ty2>
    _NODISCARD bool operator<(const shared_ptr<_Ty1>& _Left, const shared_ptr<_Ty2>& _Right) noexcept
    {
    return (_Left.get() < _Right.get());
    }

template<class _Ty1,
    class _Ty2>
    _NODISCARD bool operator>=(const shared_ptr<_Ty1>& _Left, const shared_ptr<_Ty2>& _Right) noexcept
    {
    return (_Left.get() >= _Right.get());
    }

template<class _Ty1,
    class _Ty2>
    _NODISCARD bool operator>(const shared_ptr<_Ty1>& _Left, const shared_ptr<_Ty2>& _Right) noexcept
    {
    return (_Left.get() > _Right.get());
    }

template<class _Ty1,
    class _Ty2>
    _NODISCARD bool operator<=(const shared_ptr<_Ty1>& _Left, const shared_ptr<_Ty2>& _Right) noexcept
    {
    return (_Left.get() <= _Right.get());
    }

template<class _Ty>
    _NODISCARD bool operator==(const shared_ptr<_Ty>& _Left, nullptr_t) noexcept
    {
    return (_Left.get() == nullptr);
    }

template<class _Ty>
    _NODISCARD bool operator==(nullptr_t, const shared_ptr<_Ty>& _Right) noexcept
    {
    return (nullptr == _Right.get());
    }

template<class _Ty>
    _NODISCARD bool operator!=(const shared_ptr<_Ty>& _Left, nullptr_t) noexcept
    {
    return (_Left.get() != nullptr);
    }

template<class _Ty>
    _NODISCARD bool operator!=(nullptr_t, const shared_ptr<_Ty>& _Right) noexcept
    {
    return (nullptr != _Right.get());
    }

template<class _Ty>
    _NODISCARD bool operator<(const shared_ptr<_Ty>& _Left, nullptr_t) noexcept
    {
    return (_Left.get() < static_cast<typename shared_ptr<_Ty>::element_type *>(nullptr));
    }

template<class _Ty>
    _NODISCARD bool operator<(nullptr_t, const shared_ptr<_Ty>& _Right) noexcept
    {
    return (static_cast<typename shared_ptr<_Ty>::element_type *>(nullptr) < _Right.get());
    }

template<class _Ty>
    _NODISCARD bool operator>=(const shared_ptr<_Ty>& _Left, nullptr_t) noexcept
    {
    return (_Left.get() >= static_cast<typename shared_ptr<_Ty>::element_type *>(nullptr));
    }

template<class _Ty>
    _NODISCARD bool operator>=(nullptr_t, const shared_ptr<_Ty>& _Right) noexcept
    {
    return (static_cast<typename shared_ptr<_Ty>::element_type *>(nullptr) >= _Right.get());
    }

template<class _Ty>
    _NODISCARD bool operator>(const shared_ptr<_Ty>& _Left, nullptr_t) noexcept
    {
    return (_Left.get() > static_cast<typename shared_ptr<_Ty>::element_type *>(nullptr));
    }

template<class _Ty>
    _NODISCARD bool operator>(nullptr_t, const shared_ptr<_Ty>& _Right) noexcept
    {
    return (static_cast<typename shared_ptr<_Ty>::element_type *>(nullptr) > _Right.get());
    }

template<class _Ty>
    _NODISCARD bool operator<=(const shared_ptr<_Ty>& _Left, nullptr_t) noexcept
    {
    return (_Left.get() <= static_cast<typename shared_ptr<_Ty>::element_type *>(nullptr));
    }

template<class _Ty>
    _NODISCARD bool operator<=(nullptr_t, const shared_ptr<_Ty>& _Right) noexcept
    {
    return (static_cast<typename shared_ptr<_Ty>::element_type *>(nullptr) <= _Right.get());
    }

template<class _Elem,
    class _Traits,
    class _Ty>
    basic_ostream<_Elem, _Traits>& operator<<(basic_ostream<_Elem, _Traits>& _Out, const shared_ptr<_Ty>& _Px)
    {    // write contained pointer to stream
    return (_Out << _Px.get());
    }

template<class _Ty>
    void swap(shared_ptr<_Ty>& _Left, shared_ptr<_Ty>& _Right) noexcept
    {    // swap _Left and _Right shared_ptrs
    _Left.swap(_Right);
    }

template<class _Ty1,
    class _Ty2>
    _NODISCARD shared_ptr<_Ty1> static_pointer_cast(const shared_ptr<_Ty2>& _Other) noexcept
    {    // static_cast for shared_ptr that properly respects the reference count control block
    const auto _Ptr = static_cast<typename shared_ptr<_Ty1>::element_type *>(_Other.get());
    return (shared_ptr<_Ty1>(_Other, _Ptr));
    }

template<class _Ty1,
    class _Ty2>
    _NODISCARD shared_ptr<_Ty1> const_pointer_cast(const shared_ptr<_Ty2>& _Other) noexcept
    {    // const_cast for shared_ptr that properly respects the reference count control block
    const auto _Ptr = const_cast<typename shared_ptr<_Ty1>::element_type *>(_Other.get());
    return (shared_ptr<_Ty1>(_Other, _Ptr));
    }

template<class _Ty1,
    class _Ty2>
    _NODISCARD shared_ptr<_Ty1> reinterpret_pointer_cast(const shared_ptr<_Ty2>& _Other) noexcept
    {    // reinterpret_cast for shared_ptr that properly respects the reference count control block
    const auto _Ptr = reinterpret_cast<typename shared_ptr<_Ty1>::element_type *>(_Other.get());
    return (shared_ptr<_Ty1>(_Other, _Ptr));
    }

#ifdef _CPPRTTI
template<class _Ty1,
    class _Ty2>
    _NODISCARD shared_ptr<_Ty1> dynamic_pointer_cast(const shared_ptr<_Ty2>& _Other) noexcept
    {    // dynamic_cast for shared_ptr that properly respects the reference count control block
    const auto _Ptr = dynamic_cast<typename shared_ptr<_Ty1>::element_type *>(_Other.get());

    if (_Ptr)
        {
        return (shared_ptr<_Ty1>(_Other, _Ptr));
        }

    return (shared_ptr<_Ty1>());
    }
#else /* _CPPRTTI */
template<class _Ty1,
    class _Ty2>
    shared_ptr<_Ty1> dynamic_pointer_cast(const shared_ptr<_Ty2>&) noexcept = delete;    // requires /GR option
#endif /* _CPPRTTI */

#if _HAS_STATIC_RTTI
template<class _Dx,
    class _Ty>
    _NODISCARD _Dx * get_deleter(const shared_ptr<_Ty>& _Sx) noexcept
    {    // return pointer to shared_ptr's deleter object if its type is _Dx
    if (_Sx._Rep)
        {
        return (static_cast<_Dx *>(_Sx._Rep->_Get_deleter(typeid(_Dx))));
        }

    return (nullptr);
    }
#else /* _HAS_STATIC_RTTI */
template<class _Dx,
    class _Ty>
    _Dx * get_deleter(const shared_ptr<_Ty>&) noexcept = delete;    // requires static RTTI
#endif /* _HAS_STATIC_RTTI */

    // CLASS TEMPLATE _Ref_count_obj
template<class _Ty>
    class _Ref_count_obj
        : public _Ref_count_base
    {    // handle reference counting for object in control block, no allocator
public:
    template<class... _Types>
        explicit _Ref_count_obj(_Types&&... _Args)
        : _Ref_count_base()
        {    // construct from argument list
        ::new (static_cast<void *>(&_Storage)) _Ty(_STD forward<_Types>(_Args)...);
        }

    _Ty * _Getptr()
        {    // get pointer
        return (reinterpret_cast<_Ty *>(&_Storage));
        }

private:
    virtual void _Destroy() noexcept override
        {    // destroy managed resource
        _Getptr()->~_Ty();
        }

    virtual void _Delete_this() noexcept override
        {    // destroy self
        delete this;
        }

    aligned_union_t<1, _Ty> _Storage;
    };
 

// CLASS TEMPLATE weak_ptr
template<class _Ty>
    class weak_ptr
        : public _Ptr_base<_Ty>
    {    // class for pointer to reference counted resource
public:
    constexpr weak_ptr() noexcept
        {    // construct empty weak_ptr object
        }

    weak_ptr(const weak_ptr& _Other) noexcept
        {    // construct weak_ptr object for resource pointed to by _Other
        this->_Weakly_construct_from(_Other);
        }

    template<class _Ty2,
        enable_if_t<_SP_pointer_compatible<_Ty2, _Ty>::value, int> = 0>
        weak_ptr(const shared_ptr<_Ty2>& _Other) noexcept
        {    // construct weak_ptr object for resource owned by _Other
        this->_Weakly_construct_from(_Other);
        }

    template<class _Ty2,
        enable_if_t<_SP_pointer_compatible<_Ty2, _Ty>::value, int> = 0>
        weak_ptr(const weak_ptr<_Ty2>& _Other) noexcept
        {    // construct weak_ptr object for resource pointed to by _Other
        this->_Weakly_construct_from(_Other.lock());
        }

    weak_ptr(weak_ptr&& _Other) noexcept
        {    // move construct from _Other
        this->_Move_construct_from(_STD move(_Other));
        }

    template<class _Ty2,
        enable_if_t<_SP_pointer_compatible<_Ty2, _Ty>::value, int> = 0>
        weak_ptr(weak_ptr<_Ty2>&& _Other) noexcept
        {    // move construct from _Other
        this->_Weakly_construct_from(_Other.lock());
        _Other.reset();
        }

    ~weak_ptr() noexcept
        {    // release resource
        this->_Decwref();
        }

    weak_ptr& operator=(const weak_ptr& _Right) noexcept
        {    // assign from _Right
        weak_ptr(_Right).swap(*this);
        return (*this);
        }

    template<class _Ty2>
        weak_ptr& operator=(const weak_ptr<_Ty2>& _Right) noexcept
        {    // assign from _Right
        weak_ptr(_Right).swap(*this);
        return (*this);
        }

    weak_ptr& operator=(weak_ptr&& _Right) noexcept
        {    // move assign from _Right
        weak_ptr(_STD move(_Right)).swap(*this);
        return (*this);
        }

    template<class _Ty2>
        weak_ptr& operator=(weak_ptr<_Ty2>&& _Right) noexcept
        {    // move assign from _Right
        weak_ptr(_STD move(_Right)).swap(*this);
        return (*this);
        }

    template<class _Ty2>
        weak_ptr& operator=(const shared_ptr<_Ty2>& _Right) noexcept
        {    // assign from _Right
        weak_ptr(_Right).swap(*this);
        return (*this);
        }

    void reset() noexcept
        {    // release resource, convert to null weak_ptr object
        weak_ptr().swap(*this);
        }

    void swap(weak_ptr& _Other) noexcept
        {    // swap pointers
        this->_Swap(_Other);
        }

    _NODISCARD bool expired() const noexcept
        {    // return true if resource no longer exists
        return (this->use_count() == 0);
        }

    _NODISCARD shared_ptr<_Ty> lock() const noexcept
        {    // convert to shared_ptr
        shared_ptr<_Ty> _Ret;
        (void) _Ret._Construct_from_weak(*this);
        return (_Ret);
        }
    };

#if _HAS_CXX17
template<class _Ty>
    weak_ptr(shared_ptr<_Ty>) -> weak_ptr<_Ty>;
#endif /* _HAS_CXX17 */

template<class _Ty>
    void swap(weak_ptr<_Ty>& _Left, weak_ptr<_Ty>& _Right) noexcept
    {    // swap contents of _Left and _Right
    _Left.swap(_Right);
    }

    // CLASS TEMPLATE enable_shared_from_this
template<class _Ty>
    class enable_shared_from_this
    {    // provide member functions that create shared_ptr to this
public:
    using _Esft_type = enable_shared_from_this;

    _NODISCARD shared_ptr<_Ty> shared_from_this()
        {    // return shared_ptr
        return (shared_ptr<_Ty>(_Wptr));
        }

    _NODISCARD shared_ptr<const _Ty> shared_from_this() const
        {    // return shared_ptr
        return (shared_ptr<const _Ty>(_Wptr));
        }

    _NODISCARD weak_ptr<_Ty> weak_from_this() noexcept
        {    // return weak_ptr
        return (_Wptr);
        }

    _NODISCARD weak_ptr<const _Ty> weak_from_this() const noexcept
        {    // return weak_ptr
        return (_Wptr);
        }

protected:
    constexpr enable_shared_from_this() noexcept
        : _Wptr()
        {    // construct
        }

    enable_shared_from_this(const enable_shared_from_this&) noexcept
        : _Wptr()
        {    // construct (must value-initialize _Wptr)
        }

    enable_shared_from_this& operator=(const enable_shared_from_this&) noexcept
        {    // assign (must not change _Wptr)
        return (*this);
        }

    ~enable_shared_from_this() = default;

private:
    template<class _Other,
        class _Yty>
        friend void _Enable_shared_from_this1(const shared_ptr<_Other>& _This, _Yty * _Ptr, true_type);

    mutable weak_ptr<_Ty> _Wptr;
    };

 

    // CLASS TEMPLATE unique_ptr SCALAR
template<class _Ty,
    class _Dx>    // = default_delete<_Ty>
    class unique_ptr
        : public _Unique_ptr_base<_Ty, _Dx>
    {    // non-copyable pointer to an object
public:
    typedef _Unique_ptr_base<_Ty, _Dx> _Mybase;
    typedef typename _Mybase::pointer pointer;
    typedef _Ty element_type;
    typedef _Dx deleter_type;

    using _Mybase::get_deleter;

    template<class _Dx2 = _Dx,
        _Unique_ptr_enable_default_t<_Dx2> = 0>
        constexpr unique_ptr() noexcept
            : _Mybase(pointer())
        {    // default construct
        }

    template<class _Dx2 = _Dx,
        _Unique_ptr_enable_default_t<_Dx2> = 0>
        constexpr unique_ptr(nullptr_t) noexcept
            : _Mybase(pointer())
        {    // null pointer construct
        }

    unique_ptr& operator=(nullptr_t) noexcept
        {    // assign a null pointer
        reset();
        return (*this);
        }

    template<class _Dx2 = _Dx,
        _Unique_ptr_enable_default_t<_Dx2> = 0>
        explicit unique_ptr(pointer _Ptr) noexcept
            : _Mybase(_Ptr)
        {    // construct with pointer
        }

    template<class _Dx2 = _Dx,
        enable_if_t<is_constructible_v<_Dx2, const _Dx2&>, int> = 0>
        unique_ptr(pointer _Ptr, const _Dx& _Dt) noexcept
            : _Mybase(_Ptr, _Dt)
        {    // construct with pointer and (maybe const) deleter&
        }

    template<class _Dx2 = _Dx,
        enable_if_t<conjunction_v<negation<is_reference<_Dx2>>,
            is_constructible<_Dx2, _Dx2>>, int> = 0>
        unique_ptr(pointer _Ptr, _Dx&& _Dt) noexcept
            : _Mybase(_Ptr, _STD move(_Dt))
        {    // construct by moving deleter
        }

    template<class _Dx2 = _Dx,
        enable_if_t<conjunction_v<is_reference<_Dx2>,
            is_constructible<_Dx2, remove_reference_t<_Dx2>>>, int> = 0>
        unique_ptr(pointer, remove_reference_t<_Dx>&&) = delete;

    unique_ptr(unique_ptr&& _Right) noexcept
        : _Mybase(_Right.release(),
            _STD forward<_Dx>(_Right.get_deleter()))
        {    // construct by moving _Right
        }

    template<class _Ty2,
        class _Dx2,
        enable_if_t<conjunction_v<negation<is_array<_Ty2>>,
            is_convertible<typename unique_ptr<_Ty2, _Dx2>::pointer, pointer>,
            conditional_t<is_reference_v<_Dx>, is_same<_Dx2, _Dx>, is_convertible<_Dx2, _Dx>>
        >, int> = 0>
        unique_ptr(unique_ptr<_Ty2, _Dx2>&& _Right) noexcept
            : _Mybase(_Right.release(),
                _STD forward<_Dx2>(_Right.get_deleter()))
        {    // construct by moving _Right
        }

 #if _HAS_AUTO_PTR_ETC
    template<class _Ty2,
        enable_if_t<conjunction_v<is_convertible<_Ty2 *, _Ty *>,
            is_same<_Dx, default_delete<_Ty>>>, int> = 0>
        unique_ptr(auto_ptr<_Ty2>&& _Right) noexcept
            : _Mybase(_Right.release())
        {    // construct by moving _Right
        }
 #endif /* _HAS_AUTO_PTR_ETC */

    template<class _Ty2,
        class _Dx2,
        enable_if_t<conjunction_v<negation<is_array<_Ty2>>,
            is_assignable<_Dx&, _Dx2>,
            is_convertible<typename unique_ptr<_Ty2, _Dx2>::pointer, pointer>
        >, int> = 0>
        unique_ptr& operator=(unique_ptr<_Ty2, _Dx2>&& _Right) noexcept
        {    // assign by moving _Right
        reset(_Right.release());
        this->get_deleter() = _STD forward<_Dx2>(_Right.get_deleter());
        return (*this);
        }

    unique_ptr& operator=(unique_ptr&& _Right) noexcept
        {    // assign by moving _Right
        if (this != _STD addressof(_Right))
            {    // different, do the move
            reset(_Right.release());
            this->get_deleter() = _STD forward<_Dx>(_Right.get_deleter());
            }
        return (*this);
        }

    void swap(unique_ptr& _Right) noexcept
        {    // swap elements
        _Swap_adl(this->_Myptr(), _Right._Myptr());
        _Swap_adl(this->get_deleter(), _Right.get_deleter());
        }

    ~unique_ptr() noexcept
        {    // destroy the object
        if (get() != pointer())
            {
            this->get_deleter()(get());
            }
        }

    _NODISCARD add_lvalue_reference_t<_Ty> operator*() const
        {    // return reference to object
        return (*get());
        }

    _NODISCARD pointer operator->() const noexcept
        {    // return pointer to class object
        return (this->_Myptr());
        }

    _NODISCARD pointer get() const noexcept
        {    // return pointer to object
        return (this->_Myptr());
        }

    explicit operator bool() const noexcept
        {    // test for non-null pointer
        return (get() != pointer());
        }

    pointer release() noexcept
        {    // yield ownership of pointer
        pointer _Ans = get();
        this->_Myptr() = pointer();
        return (_Ans);
        }

    void reset(pointer _Ptr = pointer()) noexcept
        {    // establish new pointer
        pointer _Old = get();
        this->_Myptr() = _Ptr;
        if (_Old != pointer())
            {
            this->get_deleter()(_Old);
            }
        }

    unique_ptr(const unique_ptr&) = delete;
    unique_ptr& operator=(const unique_ptr&) = delete;
    };

    // CLASS TEMPLATE unique_ptr ARRAY
template<class _Ty,
    class _Dx>
    class unique_ptr<_Ty[], _Dx>
        : public _Unique_ptr_base<_Ty, _Dx>
    {    // non-copyable pointer to an array object
public:
    typedef _Unique_ptr_base<_Ty, _Dx> _Mybase;
    typedef typename _Mybase::pointer pointer;
    typedef _Ty element_type;
    typedef _Dx deleter_type;

    using _Mybase::get_deleter;

    template<class _Dx2 = _Dx,
        _Unique_ptr_enable_default_t<_Dx2> = 0>
        constexpr unique_ptr() noexcept
            : _Mybase(pointer())
        {    // default construct
        }

    template<class _Uty,
        class _Is_nullptr = is_same<_Uty, nullptr_t>>
        using _Enable_ctor_reset = enable_if_t<
            is_same_v<_Uty, pointer>
            || _Is_nullptr::value
            || (is_same_v<pointer, element_type *>
            && is_pointer_v<_Uty>
            && is_convertible_v<
                remove_pointer_t<_Uty>(*)[],
                element_type(*)[]
            >)>;

    template<class _Uty,
        class _Dx2 = _Dx,
        _Unique_ptr_enable_default_t<_Dx2> = 0,
        class = _Enable_ctor_reset<_Uty>>
        explicit unique_ptr(_Uty _Ptr) noexcept
            : _Mybase(_Ptr)
        {    // construct with pointer
        }

    template<class _Uty,
        class _Dx2 = _Dx,
        enable_if_t<is_constructible_v<_Dx2, const _Dx2&>, int> = 0,
        class = _Enable_ctor_reset<_Uty>>
        unique_ptr(_Uty _Ptr, const _Dx& _Dt) noexcept
            : _Mybase(_Ptr, _Dt)
        {    // construct with pointer and (maybe const) deleter&
        }

    template<class _Uty,
        class _Dx2 = _Dx,
        enable_if_t<conjunction_v<negation<is_reference<_Dx2>>,
            is_constructible<_Dx2, _Dx2>>, int> = 0,
        class = _Enable_ctor_reset<_Uty>>
        unique_ptr(_Uty _Ptr, _Dx&& _Dt) noexcept
            : _Mybase(_Ptr, _STD move(_Dt))
        {    // construct by moving deleter
        }

    template<class _Uty,
        class _Dx2 = _Dx,
        enable_if_t<conjunction_v<is_reference<_Dx2>,
            is_constructible<_Dx2, remove_reference_t<_Dx2>>>, int> = 0>
        unique_ptr(_Uty, remove_reference_t<_Dx>&&) = delete;

    unique_ptr(unique_ptr&& _Right) noexcept
        : _Mybase(_Right.release(),
            _STD forward<_Dx>(_Right.get_deleter()))
        {    // construct by moving _Right
        }

    unique_ptr& operator=(unique_ptr&& _Right) noexcept
        {    // assign by moving _Right
        if (this != _STD addressof(_Right))
            {    // different, do the swap
            reset(_Right.release());
            this->get_deleter() = _STD move(_Right.get_deleter());
            }
        return (*this);
        }

    template<class _Uty,
        class _Ex,
        class _More,
        class _UP_pointer = typename unique_ptr<_Uty, _Ex>::pointer,
        class _UP_element_type = typename unique_ptr<_Uty, _Ex>::element_type>
        using _Enable_conversion = enable_if_t<conjunction_v<
            is_array<_Uty>,
            is_same<pointer, element_type *>,
            is_same<_UP_pointer, _UP_element_type *>,
            is_convertible<_UP_element_type(*)[], element_type(*)[]>,
            _More>>;

    template<class _Uty,
        class _Ex,
        class = _Enable_conversion<_Uty, _Ex,
            conditional_t<is_reference_v<_Dx>, is_same<_Ex, _Dx>, is_convertible<_Ex, _Dx>>>>
        unique_ptr(unique_ptr<_Uty, _Ex>&& _Right) noexcept
            : _Mybase(_Right.release(),
                _STD forward<_Ex>(_Right.get_deleter()))
        {    // construct by moving _Right
        }

    template<class _Uty,
        class _Ex,
        class = _Enable_conversion<_Uty, _Ex, is_assignable<_Dx&, _Ex>>>
        unique_ptr& operator=(unique_ptr<_Uty, _Ex>&& _Right) noexcept
        {    // assign by moving _Right
        reset(_Right.release());
        this->get_deleter() = _STD forward<_Ex>(_Right.get_deleter());
        return (*this);
        }

    template<class _Dx2 = _Dx,
        _Unique_ptr_enable_default_t<_Dx2> = 0>
        constexpr unique_ptr(nullptr_t) noexcept
            : _Mybase(pointer())
        {    // null pointer construct
        }

    unique_ptr& operator=(nullptr_t) noexcept
        {    // assign a null pointer
        reset();
        return (*this);
        }

    void reset(nullptr_t = nullptr) noexcept
        {    // establish new null pointer
        reset(pointer());
        }

    void swap(unique_ptr& _Right) noexcept
        {    // swap elements
        _Swap_adl(this->_Myptr(), _Right._Myptr());
        _Swap_adl(this->get_deleter(), _Right.get_deleter());
        }

    ~unique_ptr() noexcept
        {    // destroy the object
        _Delete();
        }

    _NODISCARD _Ty& operator[](size_t _Idx) const
        {    // return reference to object
        return (get()[_Idx]);
        }

    _NODISCARD pointer get() const noexcept
        {    // return pointer to object
        return (this->_Myptr());
        }

    explicit operator bool() const noexcept
        {    // test for non-null pointer
        return (get() != pointer());
        }

    pointer release() noexcept
        {    // yield ownership of pointer
        pointer _Ans = get();
        this->_Myptr() = pointer();
        return (_Ans);
        }

    template<class _Uty,
        class = _Enable_ctor_reset<_Uty, false_type>>
        void reset(_Uty _Ptr) noexcept
        {    // establish new pointer
        pointer _Old = get();
        this->_Myptr() = _Ptr;
        if (_Old != pointer())
            {
            this->get_deleter()(_Old);
            }
        }

    unique_ptr(const unique_ptr&) = delete;
    unique_ptr& operator=(const unique_ptr&) = delete;

private:
    void _Delete()
        {    // delete the pointer
        if (get() != pointer())
            {
            this->get_deleter()(get());
            }
        }
    };


    // FUNCTION TEMPLATE make_unique
template<class _Ty,
    class... _Types,
    enable_if_t<!is_array_v<_Ty>, int> = 0>
    _NODISCARD inline unique_ptr<_Ty> make_unique(_Types&&... _Args)
    {    // make a unique_ptr
    return (unique_ptr<_Ty>(new _Ty(_STD forward<_Types>(_Args)...)));
    }

template<class _Ty,
    enable_if_t<is_array_v<_Ty> && extent_v<_Ty> == 0, int> = 0>
    _NODISCARD inline unique_ptr<_Ty> make_unique(size_t _Size)
    {    // make a unique_ptr
    typedef remove_extent_t<_Ty> _Elem;
    return (unique_ptr<_Ty>(new _Elem[_Size]()));
    }

template<class _Ty,
    class... _Types,
    enable_if_t<extent_v<_Ty> != 0, int> = 0>
    void make_unique(_Types&&...) = delete;
 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值