unique_ptr 源码分析

  1. unique_ptr

    • 简介

      • 独占

      • 实现了构造,实现了移动.

      • 不允许拷贝.

    • 实现

      • unique_ptr提供了指针拥有的接口

      • __uniq_ptr_impl提供的是数据和析构类.

  2. 源码

    • 源码

       template <typename _Tp, typename _Dp = default_delete<_Tp>>
         class unique_ptr
         {
           template <class _Up>
           using _DeleterConstraint =
         typename __uniq_ptr_impl<_Tp, _Up>::_DeleterConstraint::type;
      
           __uniq_ptr_impl<_Tp, _Dp> _M_t;
      
         public:
           using pointer   = typename __uniq_ptr_impl<_Tp, _Dp>::pointer;
           using element_type  = _Tp;
           using deleter_type  = _Dp;
      
           // helper template for detecting a safe conversion from another
           // unique_ptr
           template<typename _Up, typename _Ep>
         using __safe_conversion_up = __and_<
                 is_convertible<typename unique_ptr<_Up, _Ep>::pointer, pointer>,
                     __not_<is_array<_Up>>,
                     __or_<__and_<is_reference<deleter_type>,
                                  is_same<deleter_type, _Ep>>,
                           __and_<__not_<is_reference<deleter_type>>,
                                  is_convertible<_Ep, deleter_type>>
                     >
                   >;
      
           // Constructors.
      
           /// Default constructor, creates a unique_ptr that owns nothing.
           template <typename _Up = _Dp,
             typename = _DeleterConstraint<_Up>>
         constexpr unique_ptr() noexcept
         : _M_t()
             { }
      
           /** Takes ownership of a pointer.
            *
            * @param __p  A pointer to an object of @c element_type
            *
            * The deleter will be value-initialized.
            */
           template <typename _Up = _Dp,
             typename = _DeleterConstraint<_Up>>
         explicit
         unique_ptr(pointer __p) noexcept
         : _M_t(__p)
             { }
      
           /** Takes ownership of a pointer.
            *
            * @param __p  A pointer to an object of @c element_type
            * @param __d  A reference to a deleter.
            *
            * The deleter will be initialized with @p __d
            */
           unique_ptr(pointer __p,
           typename conditional<is_reference<deleter_type>::value,
             deleter_type, const deleter_type&>::type __d) noexcept
           : _M_t(__p, __d) { }
      
           /** Takes ownership of a pointer.
            *
            * @param __p  A pointer to an object of @c element_type
            * @param __d  An rvalue reference to a deleter.
            *
            * The deleter will be initialized with @p std::move(__d)
            */
           unique_ptr(pointer __p,
           typename remove_reference<deleter_type>::type&& __d) noexcept
           : _M_t(std::move(__p), std::move(__d))
           { static_assert(!std::is_reference<deleter_type>::value,
                   "rvalue deleter bound to reference"); }
      
           /// Creates a unique_ptr that owns nothing.
           template <typename _Up = _Dp,
             typename = _DeleterConstraint<_Up>>
         constexpr unique_ptr(nullptr_t) noexcept : unique_ptr() { }
      
           // Move constructors.
      
           /// Move constructor.
           unique_ptr(unique_ptr&& __u) noexcept
           : _M_t(__u.release(), std::forward<deleter_type>(__u.get_deleter())) { }
      
           /** @brief Converting constructor from another type
            *
            * Requires that the pointer owned by @p __u is convertible to the
            * type of pointer owned by this object, @p __u does not own an array,
            * and @p __u has a compatible deleter type.
            */
           template<typename _Up, typename _Ep, typename = _Require<
                    __safe_conversion_up<_Up, _Ep>,
                typename conditional<is_reference<_Dp>::value,
                         is_same<_Ep, _Dp>,
                         is_convertible<_Ep, _Dp>>::type>>
         unique_ptr(unique_ptr<_Up, _Ep>&& __u) noexcept
         : _M_t(__u.release(), std::forward<_Ep>(__u.get_deleter()))
         { }
      
      #if _GLIBCXX_USE_DEPRECATED
      #pragma GCC diagnostic push
      #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
           /// Converting constructor from @c auto_ptr
           template<typename _Up, typename = _Require<
                is_convertible<_Up*, _Tp*>, is_same<_Dp, default_delete<_Tp>>>>
         unique_ptr(auto_ptr<_Up>&& __u) noexcept;
      #pragma GCC diagnostic pop
      #endif
      
           /// Destructor, invokes the deleter if the stored pointer is not null.
           ~unique_ptr() noexcept
           {
         auto& __ptr = _M_t._M_ptr();
         if (__ptr != nullptr)
           get_deleter()(__ptr);
         __ptr = pointer();
           }
      
           // Assignment.
      
           /** @brief Move assignment operator.
            *
            * @param __u  The object to transfer ownership from.
            *
            * Invokes the deleter first if this object owns a pointer.
            */
           unique_ptr&
           operator=(unique_ptr&& __u) noexcept
           {
         reset(__u.release());
         get_deleter() = std::forward<deleter_type>(__u.get_deleter());
         return *this;
           }
      
           /** @brief Assignment from another type.
            *
            * @param __u  The object to transfer ownership from, which owns a
            *             convertible pointer to a non-array object.
            *
            * Invokes the deleter first if this object owns a pointer.
            */
           template<typename _Up, typename _Ep>
             typename enable_if< __and_<
               __safe_conversion_up<_Up, _Ep>,
               is_assignable<deleter_type&, _Ep&&>
               >::value,
               unique_ptr&>::type
         operator=(unique_ptr<_Up, _Ep>&& __u) noexcept
         {
           reset(__u.release());
           get_deleter() = std::forward<_Ep>(__u.get_deleter());
           return *this;
         }
      
           /// Reset the %unique_ptr to empty, invoking the deleter if necessary.
           unique_ptr&
           operator=(nullptr_t) noexcept
           {
         reset();
         return *this;
           }
      
           // Observers.
      
           /// Dereference the stored pointer.
           typename add_lvalue_reference<element_type>::type
           operator*() const
           {
         __glibcxx_assert(get() != pointer());
         return *get();
           }
      
           /// Return the stored pointer.
           pointer
           operator->() const noexcept
           {
         _GLIBCXX_DEBUG_PEDASSERT(get() != pointer());
         return get();
           }
      
           /// Return the stored pointer.
           pointer
           get() const noexcept
           { return _M_t._M_ptr(); }
      
           /// Return a reference to the stored deleter.
           deleter_type&
           get_deleter() noexcept
           { return _M_t._M_deleter(); }
      
           /// Return a reference to the stored deleter.
           const deleter_type&
           get_deleter() const noexcept
           { return _M_t._M_deleter(); }
      
           /// Return @c true if the stored pointer is not null.
           explicit operator bool() const noexcept
           { return get() == pointer() ? false : true; }
      
           // Modifiers.
      
           /// Release ownership of any stored pointer.
           pointer
           release() noexcept
           {
         pointer __p = get();
         _M_t._M_ptr() = pointer();
         return __p;
           }
      
           /** @brief Replace the stored pointer.
            *
            * @param __p  The new pointer to store.
            *
            * The deleter will be invoked if a pointer is already owned.
            */
           void
           reset(pointer __p = pointer()) noexcept
           {
         using std::swap;
         swap(_M_t._M_ptr(), __p);
         if (__p != pointer())
           get_deleter()(__p);
           }
      
           /// Exchange the pointer and deleter with another object.
           void
           swap(unique_ptr& __u) noexcept
           {
         using std::swap;
         swap(_M_t, __u._M_t);
           }
      
           // Disable copy from lvalue.
           unique_ptr(const unique_ptr&) = delete;
           unique_ptr& operator=(const unique_ptr&) = delete;
       };
      
      
    • 数据封装

       template <typename _Tp, typename _Dp>
         class __uniq_ptr_impl
         {
           template <typename _Up, typename _Ep, typename = void>
       struct _Ptr
       {
         using type = _Up*;
       };
      
           template <typename _Up, typename _Ep>
       struct
       _Ptr<_Up, _Ep, __void_t<typename remove_reference<_Ep>::type::pointer>>
       {
         using type = typename remove_reference<_Ep>::type::pointer;
       };
      
         public:
           using _DeleterConstraint = enable_if<
             __and_<__not_<is_pointer<_Dp>>,
              is_default_constructible<_Dp>>::value>;
      
           using pointer = typename _Ptr<_Tp, _Dp>::type;
      
           __uniq_ptr_impl() = default;
           __uniq_ptr_impl(pointer __p) : _M_t() { _M_ptr() = __p; }
      
           template<typename _Del>
           __uniq_ptr_impl(pointer __p, _Del&& __d)
       : _M_t(__p, std::forward<_Del>(__d)) { }
      
           pointer&   _M_ptr() { return std::get<0>(_M_t); }
           pointer    _M_ptr() const { return std::get<0>(_M_t); }
           _Dp&       _M_deleter() { return std::get<1>(_M_t); }
           const _Dp& _M_deleter() const { return std::get<1>(_M_t); }
      
         private:
           tuple<pointer, _Dp> _M_t;
         };
      
      
      • 首先是用tuple进行的数据封装.

      • tuple有个特性就是,对于空类不占内存,非空类会占用sizeof那么大的内存.

      • 具体可以看tuple源码和模板元编程.

      • 总之,数据采用并排的方式,空类不占用空间,非空类占用析构.所以非空析构对象则会占用空间.

  3. 析构

    • 默认析构

       template<typename _Tp>
         struct default_delete
         {
           /// Default constructor
           constexpr default_delete() noexcept = default;
      
           /** @brief Converting constructor.
            *
            * Allows conversion from a deleter for arrays of another type, @p _Up,
            * only if @p _Up* is convertible to @p _Tp*.
            */
           template<typename _Up, typename = typename
              enable_if<is_convertible<_Up*, _Tp*>::value>::type>
             default_delete(const default_delete<_Up>&) noexcept { }
      
           /// Calls @c delete @p __ptr
           void
           operator()(_Tp* __ptr) const
           {
       static_assert(!is_void<_Tp>::value,
               "can't delete pointer to incomplete type");
       static_assert(sizeof(_Tp)>0,
               "can't delete pointer to incomplete type");
       delete __ptr;
           }
         };
      
      
    • 自定义析构

      • 通过tuple组合起来.数据以成员变量的形式保存.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值