-
unique_ptr
-
简介
-
独占
-
实现了构造,实现了移动.
-
不允许拷贝.
-
-
实现
-
unique_ptr
提供了指针拥有的接口 -
用
__uniq_ptr_impl
提供的是数据和析构类.
-
-
-
源码
-
源码
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_ptrtemplate<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>>explicitunique_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_ptrtemplate<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&>::typeoperator=(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>::typeoperator*() const{ __glibcxx_assert(get() != pointer());return *get();}/// Return the stored pointer.pointeroperator->() const noexcept{ _GLIBCXX_DEBUG_PEDASSERT(get() != pointer());return get();}/// Return the stored pointer.pointerget() 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.pointerrelease() 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.*/voidreset(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.voidswap(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
源码和模板元编程. -
总之,数据采用并排的方式,空类不占用空间,非空类占用析构.所以非空析构对象则会占用空间.
-
-
-
析构
-
默认析构
template<typename _Tp>struct default_delete{ /// Default constructorconstexpr 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 = typenameenable_if<is_convertible<_Up*, _Tp*>::value>::type>default_delete(const default_delete<_Up>&) noexcept { }/// Calls @c delete @p __ptrvoidoperator()(_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
组合起来.数据以成员变量的形式保存.
- 通过
-
详细解决方案
unique_ptr 源码分析
热度:76 发布时间:2023-12-22 02:43:34.0
相关解决方案
- C++基础知识 - unique_ptr 使用详解 (C++11)
- C++智能指针:unique_ptr、shared_ptr、weak_ptr
- C++---智能指针(auto_ptr、unique_ptr、shared_ptr)
- std::unique_ptr<>
- unique_ptr 源码分析
- C++11 智能指针 unique_ptr,让资源管理更简单,更安全
- 【C++】智能指针(二)--unique_ptr、shared_ptr和wear_ptr
- 智能指针(详解)——unique_ptr
- C++ 11 创建和使用 unique_ptr
- C++11智能指针-unique_ptr
- std::unique_ptr 独占所有权智能指针
- C++11 - std::shared_ptr和std::unique_ptr