IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> GNU C++ 智能指针15- 解析__shared_ptr类4 -> 正文阅读

[C++知识库]GNU C++ 智能指针15- 解析__shared_ptr类4

目录

一、关键点解析

1、_S_raw_ptr

2、__addressof

4、static_pointer_cast、const_pointer_cast和dynamic_pointer_cast

5、与bool类型的转换

6、与nullptr_t的比较

二、源码分析


一、关键点解析

1、_S_raw_ptr

      template<typename _Tp1>
	static _Tp1*
	_S_raw_ptr(_Tp1* __ptr)
	{ return __ptr; }

      template<typename _Tp1>
	static auto
	_S_raw_ptr(_Tp1 __ptr) -> decltype(std::__addressof(*__ptr))
	{ return std::__addressof(*__ptr); }

? ? 对于C ++ 11,如果您想使用auto作为返回类型,则需要以这种方式描述有效的返回类型

auto funcName (args...) -> returnType

2、__addressof

namespace std _GLIBCXX_VISIBILITY(default)
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
 
  // Used, in C++03 mode too, by allocators, etc.
  /**
   *  @brief Same as C++11 std::addressof
   *  @ingroup utilities
   */
  template<typename _Tp>
    inline _Tp*
    __addressof(_Tp& __r) _GLIBCXX_NOEXCEPT
    {
      return reinterpret_cast<_Tp*>
	(&const_cast<char&>(reinterpret_cast<const volatile char&>(__r)));
    }
 
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace

__r的类型为__Tp
(1)将__r转为const volatile char&有几个作用
? (a)防止后面用&操作符获取地址时出发原类型(即__Tp)的重载操作(operator&).
? (b)reinterpret_cast操作符总是可以合法的在原类型的基础上加const或volatile, 但是如果__Tp原来带有const或volatile的话, 通过reinterpret_cast去掉是不允许的, 因此需要加上const volatile来避免编译器报错, 也就是不用在管__Tp是否是const或volatile了.
?(c)转换为char&, 因为换成其他类型有可能回触发强制地址对齐的操作, 这样的话真实地址就可能会改变, 造成Undefined Behavior.
(2)const_cast将const或volatile去掉. 因为后面我们要将获取的地址转换回__Tp*, 因为我们前面加了const, 所以这里我们再去掉。
(3)通过取地址符&获取地址后, 再通过reinterpret_cast转换回__Tp*(会保留__Tp的const或volatile如果它有这个修饰符的话)

3、operator==

? template<typename _Tp1, typename _Tp2, _Lock_policy _Lp>
? ? inline bool
? ? operator==(const __shared_ptr<_Tp1, _Lp>& __a,
?? ? ? ? ? const __shared_ptr<_Tp2, _Lp>& __b) noexcept
? ? { return __a.get() == __b.get(); }

调用

? ? ? _Tp*
? ? ? get() const noexcept
? ? ? { return _M_ptr; }


? ? ? ?_Tp*?? ? ? ?? ? ? _M_ptr; ? ? ? ? // Contained pointer.

? ? ? ?operator==还是比较包含的裸指针是否相等。

4、static_pointer_cast、const_pointer_cast和dynamic_pointer_cast

  // 20.7.2.2.9 shared_ptr casts

  // The seemingly equivalent code:
  // shared_ptr<_Tp, _Lp>(static_cast<_Tp*>(__r.get()))
  // will eventually result in undefined behaviour, attempting to
  // delete the same object twice.
  /// static_pointer_cast
  template<typename _Tp, typename _Tp1, _Lock_policy _Lp>
    inline __shared_ptr<_Tp, _Lp>
    static_pointer_cast(const __shared_ptr<_Tp1, _Lp>& __r) noexcept
    { return __shared_ptr<_Tp, _Lp>(__r, static_cast<_Tp*>(__r.get())); }

  // The seemingly equivalent code:
  // shared_ptr<_Tp, _Lp>(const_cast<_Tp*>(__r.get()))
  // will eventually result in undefined behaviour, attempting to
  // delete the same object twice.
  /// const_pointer_cast
  template<typename _Tp, typename _Tp1, _Lock_policy _Lp>
    inline __shared_ptr<_Tp, _Lp>
    const_pointer_cast(const __shared_ptr<_Tp1, _Lp>& __r) noexcept
    { return __shared_ptr<_Tp, _Lp>(__r, const_cast<_Tp*>(__r.get())); }

  // The seemingly equivalent code:
  // shared_ptr<_Tp, _Lp>(dynamic_cast<_Tp*>(__r.get()))
  // will eventually result in undefined behaviour, attempting to
  // delete the same object twice.
  /// dynamic_pointer_cast
  template<typename _Tp, typename _Tp1, _Lock_policy _Lp>
    inline __shared_ptr<_Tp, _Lp>
    dynamic_pointer_cast(const __shared_ptr<_Tp1, _Lp>& __r) noexcept
    {
      if (_Tp* __p = dynamic_cast<_Tp*>(__r.get()))
	return __shared_ptr<_Tp, _Lp>(__r, __p);
      return __shared_ptr<_Tp, _Lp>();
    }

? ? ? ?shared_ptr<_Tp, _Lp>(static_cast<_Tp*>(__r.get()))这种代码会造成二次释放,产生未定义的结果,shared_ptr<_Tp, _Lp>(const_cast<_Tp*>(__r.get()))和shared_ptr<_Tp, _Lp>(dynamic_cast<_Tp*>(__r.get()))也是一样的。所以提供了特殊版本static_pointer_cast、const_pointer_cast和dynamic_pointer_cast用来转换。

? ? 语句return __shared_ptr<_Tp, _Lp>(__r, static_cast<_Tp*>(__r.get()))会调用下面的构造函数:

? ? ? template<typename _Tp1>
?? ?__shared_ptr(const __shared_ptr<_Tp1, _Lp>& __r, _Tp* __p) noexcept
?? ?: _M_ptr(__p), _M_refcount(__r._M_refcount) // never throws
?? ?{ }

? ?_M_refcount(__r._M_refcount)会调用下面的构造函数:

? __shared_count(const __shared_count& __r) noexcept
? ? ? : _M_pi(__r._M_pi)
? ? ? {
?? ?if (_M_pi != 0)
?? ? ?_M_pi->_M_add_ref_copy();
? ? ? }

5、与bool类型的转换

      explicit operator bool() const // never throws
      { return _M_ptr == 0 ? false : true; }

? ?通过重载操作符与bool类型进行转换。

6、与nullptr_t的比较

? template<typename _Tp, _Lock_policy _Lp>
? ? inline bool
? ? operator==(const __shared_ptr<_Tp, _Lp>& __a, nullptr_t) noexcept
? ? { return !__a; }

? ? ?这个会调用到5中的内容,先转换到bool类型,然后再取反。
?

二、源码分析

  template<typename _Tp, _Lock_policy _Lp>
    class __shared_ptr
    {
    public:
      typedef _Tp   element_type;// element_type即为_Tp类型
 
      constexpr __shared_ptr() noexcept//constexpr 构造函数
      : _M_ptr(0), _M_refcount()
      { }
 
      template<typename _Tp1>
	explicit __shared_ptr(_Tp1* __p)
        : _M_ptr(__p), _M_refcount(__p)
	{
	  __glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>)//指针时可以赋值的
	  static_assert( !is_void<_Tp1>::value, "incomplete type" );//不是void类型
	  static_assert( sizeof(_Tp1) > 0, "incomplete type" );//类型大小大于0
	  __enable_shared_from_this_helper(_M_refcount, __p, __p);//添加一个弱引用
	}
 
      template<typename _Tp1, typename _Deleter>
	__shared_ptr(_Tp1* __p, _Deleter __d)
	: _M_ptr(__p), _M_refcount(__p, __d)//构造函数
	{
	  __glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>)
	  // TODO requires _Deleter CopyConstructible and __d(__p) well-formed
	  __enable_shared_from_this_helper(_M_refcount, __p, __p);
	}
 
      template<typename _Tp1, typename _Deleter, typename _Alloc>
	__shared_ptr(_Tp1* __p, _Deleter __d, _Alloc __a)//构造函数
	: _M_ptr(__p), _M_refcount(__p, __d, std::move(__a))
	{
	  __glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>)
	  // TODO requires _Deleter CopyConstructible and __d(__p) well-formed
	  __enable_shared_from_this_helper(_M_refcount, __p, __p);
	}
 
      template<typename _Deleter>
	__shared_ptr(nullptr_t __p, _Deleter __d)
	: _M_ptr(0), _M_refcount(__p, __d)
	{ }
 
      template<typename _Deleter, typename _Alloc>
        __shared_ptr(nullptr_t __p, _Deleter __d, _Alloc __a)
	: _M_ptr(0), _M_refcount(__p, __d, std::move(__a))
	{ }
 
      template<typename _Tp1>
	__shared_ptr(const __shared_ptr<_Tp1, _Lp>& __r, _Tp* __p) noexcept
	: _M_ptr(__p), _M_refcount(__r._M_refcount) // never throws
	{ }
 
      __shared_ptr(const __shared_ptr&) noexcept = default;
      __shared_ptr& operator=(const __shared_ptr&) noexcept = default;
      ~__shared_ptr() = default;
 
      template<typename _Tp1, typename = typename
	       std::enable_if<std::is_convertible<_Tp1*, _Tp*>::value>::type>
	__shared_ptr(const __shared_ptr<_Tp1, _Lp>& __r) noexcept
	: _M_ptr(__r._M_ptr), _M_refcount(__r._M_refcount)
	{ }
 
      __shared_ptr(__shared_ptr&& __r) noexcept//右值构造函数实现move语义
      : _M_ptr(__r._M_ptr), _M_refcount()
      {
	_M_refcount._M_swap(__r._M_refcount);//调用__shared_count类中的_M_swap
	__r._M_ptr = 0;
      }
 
      template<typename _Tp1, typename = typename
	       std::enable_if<std::is_convertible<_Tp1*, _Tp*>::value>::type>
	__shared_ptr(__shared_ptr<_Tp1, _Lp>&& __r) noexcept
	: _M_ptr(__r._M_ptr), _M_refcount()
	{
	  _M_refcount._M_swap(__r._M_refcount);
	  __r._M_ptr = 0;
	}
 
      template<typename _Tp1>
	explicit __shared_ptr(const __weak_ptr<_Tp1, _Lp>& __r)
	: _M_refcount(__r._M_refcount) // may throw
	{
	  __glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>)
 
	  // It is now safe to copy __r._M_ptr, as
	  // _M_refcount(__r._M_refcount) did not throw.
	  _M_ptr = __r._M_ptr;
	}
 
      // If an exception is thrown this constructor has no effect.
      template<typename _Tp1, typename _Del>
	__shared_ptr(std::unique_ptr<_Tp1, _Del>&& __r)
	: _M_ptr(__r.get()), _M_refcount()
	{
	  __glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>)
	  auto __raw = _S_raw_ptr(__r.get());
	  _M_refcount = __shared_count<_Lp>(std::move(__r));
	  __enable_shared_from_this_helper(_M_refcount, __raw, __raw);
	}
 
#if _GLIBCXX_USE_DEPRECATED
      // Postcondition: use_count() == 1 and __r.get() == 0
      template<typename _Tp1>
	__shared_ptr(std::auto_ptr<_Tp1>&& __r);
#endif
 
      /* TODO: use delegating constructor */
      constexpr __shared_ptr(nullptr_t) noexcept
      : _M_ptr(0), _M_refcount()
      { }
 
      template<typename _Tp1>
	__shared_ptr&
	operator=(const __shared_ptr<_Tp1, _Lp>& __r) noexcept
	{
	  _M_ptr = __r._M_ptr;
	  _M_refcount = __r._M_refcount; // __shared_count::op= doesn't throw
	  return *this;
	}
 
#if _GLIBCXX_USE_DEPRECATED
      template<typename _Tp1>
	__shared_ptr&
	operator=(std::auto_ptr<_Tp1>&& __r)
	{
	  __shared_ptr(std::move(__r)).swap(*this);
	  return *this;
	}
#endif
 
      __shared_ptr&
      operator=(__shared_ptr&& __r) noexcept
      {
	__shared_ptr(std::move(__r)).swap(*this);
	return *this;
      }
 
      template<class _Tp1>
	__shared_ptr&
	operator=(__shared_ptr<_Tp1, _Lp>&& __r) noexcept
	{
	  __shared_ptr(std::move(__r)).swap(*this);
	  return *this;
	}
 
      template<typename _Tp1, typename _Del>
	__shared_ptr&
	operator=(std::unique_ptr<_Tp1, _Del>&& __r)
	{
	  __shared_ptr(std::move(__r)).swap(*this);
	  return *this;
	}
 
      void
      reset() noexcept
      { __shared_ptr().swap(*this); }
 
      template<typename _Tp1>
	void
	reset(_Tp1* __p) // _Tp1 must be complete.
	{
	  // Catch self-reset errors.
	  _GLIBCXX_DEBUG_ASSERT(__p == 0 || __p != _M_ptr);
	  __shared_ptr(__p).swap(*this);
	}
 
      template<typename _Tp1, typename _Deleter>
	void
	reset(_Tp1* __p, _Deleter __d)
	{ __shared_ptr(__p, __d).swap(*this); }
 
      template<typename _Tp1, typename _Deleter, typename _Alloc>
	void
        reset(_Tp1* __p, _Deleter __d, _Alloc __a)
        { __shared_ptr(__p, __d, std::move(__a)).swap(*this); }
 
      // Allow class instantiation when _Tp is [cv-qual] void.
      typename std::add_lvalue_reference<_Tp>::type
      operator*() const noexcept
      {
	_GLIBCXX_DEBUG_ASSERT(_M_ptr != 0);
	return *_M_ptr;
      }
 
      _Tp*
      operator->() const noexcept
      {
	_GLIBCXX_DEBUG_ASSERT(_M_ptr != 0);
	return _M_ptr;
      }
 
      _Tp*
      get() const noexcept
      { return _M_ptr; }
 
      explicit operator bool() const // never throws
      { return _M_ptr == 0 ? false : true; }
 
      bool
      unique() const noexcept
      { return _M_refcount._M_unique(); }
 
      long
      use_count() const noexcept
      { return _M_refcount._M_get_use_count(); }
 
      void
      swap(__shared_ptr<_Tp, _Lp>& __other) noexcept
      {
	std::swap(_M_ptr, __other._M_ptr);
	_M_refcount._M_swap(__other._M_refcount);
      }
 
      template<typename _Tp1>
	bool
	owner_before(__shared_ptr<_Tp1, _Lp> const& __rhs) const
	{ return _M_refcount._M_less(__rhs._M_refcount); }
 
      template<typename _Tp1>
	bool
	owner_before(__weak_ptr<_Tp1, _Lp> const& __rhs) const
	{ return _M_refcount._M_less(__rhs._M_refcount); }
 
#ifdef __GXX_RTTI
    protected:
      // This constructor is non-standard, it is used by allocate_shared.
      template<typename _Alloc, typename... _Args>
	__shared_ptr(_Sp_make_shared_tag __tag, const _Alloc& __a,
		     _Args&&... __args)
	: _M_ptr(), _M_refcount(__tag, (_Tp*)0, __a,
				std::forward<_Args>(__args)...)
	{
	  // _M_ptr needs to point to the newly constructed object.
	  // This relies on _Sp_counted_ptr_inplace::_M_get_deleter.
	  void* __p = _M_refcount._M_get_deleter(typeid(__tag));
	  _M_ptr = static_cast<_Tp*>(__p);
	  __enable_shared_from_this_helper(_M_refcount, _M_ptr, _M_ptr);
	}
#else
      template<typename _Alloc>
        struct _Deleter
        {
          void operator()(_Tp* __ptr)
          {
	    typedef allocator_traits<_Alloc> _Alloc_traits;
	    _Alloc_traits::destroy(_M_alloc, __ptr);
	    _Alloc_traits::deallocate(_M_alloc, __ptr, 1);
          }
          _Alloc _M_alloc;
        };
 
      template<typename _Alloc, typename... _Args>
	__shared_ptr(_Sp_make_shared_tag __tag, const _Alloc& __a,
		     _Args&&... __args)
	: _M_ptr(), _M_refcount()
        {
	  typedef typename _Alloc::template rebind<_Tp>::other _Alloc2;
          _Deleter<_Alloc2> __del = { _Alloc2(__a) };
	  typedef allocator_traits<_Alloc2> __traits;
          _M_ptr = __traits::allocate(__del._M_alloc, 1);
	  __try
	    {
	      // _GLIBCXX_RESOLVE_LIB_DEFECTS
	      // 2070. allocate_shared should use allocator_traits<A>::construct
	      __traits::construct(__del._M_alloc, _M_ptr,
		                  std::forward<_Args>(__args)...);
	    }
	  __catch(...)
	    {
	      __traits::deallocate(__del._M_alloc, _M_ptr, 1);
	      __throw_exception_again;
	    }
          __shared_count<_Lp> __count(_M_ptr, __del, __del._M_alloc);
          _M_refcount._M_swap(__count);
	  __enable_shared_from_this_helper(_M_refcount, _M_ptr, _M_ptr);
        }
#endif
 
      template<typename _Tp1, _Lock_policy _Lp1, typename _Alloc,
	       typename... _Args>
	friend __shared_ptr<_Tp1, _Lp1>
	__allocate_shared(const _Alloc& __a, _Args&&... __args);
 
      // This constructor is used by __weak_ptr::lock() and
      // shared_ptr::shared_ptr(const weak_ptr&, std::nothrow_t).
      __shared_ptr(const __weak_ptr<_Tp, _Lp>& __r, std::nothrow_t)
      : _M_refcount(__r._M_refcount, std::nothrow)
      {
	_M_ptr = _M_refcount._M_get_use_count() ? __r._M_ptr : nullptr;
      }
 
      friend class __weak_ptr<_Tp, _Lp>;
 
    private:
      void*
      _M_get_deleter(const std::type_info& __ti) const noexcept
      { return _M_refcount._M_get_deleter(__ti); }
 
      template<typename _Tp1>
	static _Tp1*
	_S_raw_ptr(_Tp1* __ptr)
	{ return __ptr; }
 
      template<typename _Tp1>
	static auto
	_S_raw_ptr(_Tp1 __ptr) -> decltype(std::__addressof(*__ptr))
	{ return std::__addressof(*__ptr); }
 
      template<typename _Tp1, _Lock_policy _Lp1> friend class __shared_ptr;
      template<typename _Tp1, _Lock_policy _Lp1> friend class __weak_ptr;
 
      template<typename _Del, typename _Tp1, _Lock_policy _Lp1>
	friend _Del* get_deleter(const __shared_ptr<_Tp1, _Lp1>&) noexcept;
 
      _Tp*	   	   _M_ptr;         // Contained pointer.
      __shared_count<_Lp>  _M_refcount;    // Reference counter.
    };
 // 20.7.2.2.7 shared_ptr comparisons
  template<typename _Tp1, typename _Tp2, _Lock_policy _Lp>
    inline bool
    operator==(const __shared_ptr<_Tp1, _Lp>& __a,
	       const __shared_ptr<_Tp2, _Lp>& __b) noexcept
    { return __a.get() == __b.get(); }

  template<typename _Tp, _Lock_policy _Lp>
    inline bool
    operator==(const __shared_ptr<_Tp, _Lp>& __a, nullptr_t) noexcept
    { return !__a; }

  template<typename _Tp, _Lock_policy _Lp>
    inline bool
    operator==(nullptr_t, const __shared_ptr<_Tp, _Lp>& __a) noexcept
    { return !__a; }

  template<typename _Tp1, typename _Tp2, _Lock_policy _Lp>
    inline bool
    operator!=(const __shared_ptr<_Tp1, _Lp>& __a,
	       const __shared_ptr<_Tp2, _Lp>& __b) noexcept
    { return __a.get() != __b.get(); }

  template<typename _Tp, _Lock_policy _Lp>
    inline bool
    operator!=(const __shared_ptr<_Tp, _Lp>& __a, nullptr_t) noexcept
    { return (bool)__a; }

  template<typename _Tp, _Lock_policy _Lp>
    inline bool
    operator!=(nullptr_t, const __shared_ptr<_Tp, _Lp>& __a) noexcept
    { return (bool)__a; }

  template<typename _Tp1, typename _Tp2, _Lock_policy _Lp>
    inline bool
    operator<(const __shared_ptr<_Tp1, _Lp>& __a,
	      const __shared_ptr<_Tp2, _Lp>& __b) noexcept
    {
      typedef typename std::common_type<_Tp1*, _Tp2*>::type _CT;
      return std::less<_CT>()(__a.get(), __b.get());
    }

  template<typename _Tp, _Lock_policy _Lp>
    inline bool
    operator<(const __shared_ptr<_Tp, _Lp>& __a, nullptr_t) noexcept
    { return std::less<_Tp*>()(__a.get(), nullptr); }

  template<typename _Tp, _Lock_policy _Lp>
    inline bool
    operator<(nullptr_t, const __shared_ptr<_Tp, _Lp>& __a) noexcept
    { return std::less<_Tp*>()(nullptr, __a.get()); }

  template<typename _Tp1, typename _Tp2, _Lock_policy _Lp>
    inline bool
    operator<=(const __shared_ptr<_Tp1, _Lp>& __a,
	       const __shared_ptr<_Tp2, _Lp>& __b) noexcept
    { return !(__b < __a); }

  template<typename _Tp, _Lock_policy _Lp>
    inline bool
    operator<=(const __shared_ptr<_Tp, _Lp>& __a, nullptr_t) noexcept
    { return !(nullptr < __a); }

  template<typename _Tp, _Lock_policy _Lp>
    inline bool
    operator<=(nullptr_t, const __shared_ptr<_Tp, _Lp>& __a) noexcept
    { return !(__a < nullptr); }

  template<typename _Tp1, typename _Tp2, _Lock_policy _Lp>
    inline bool
    operator>(const __shared_ptr<_Tp1, _Lp>& __a,
	      const __shared_ptr<_Tp2, _Lp>& __b) noexcept
    { return (__b < __a); }

  template<typename _Tp, _Lock_policy _Lp>
    inline bool
    operator>(const __shared_ptr<_Tp, _Lp>& __a, nullptr_t) noexcept
    { return std::less<_Tp*>()(nullptr, __a.get()); }

  template<typename _Tp, _Lock_policy _Lp>
    inline bool
    operator>(nullptr_t, const __shared_ptr<_Tp, _Lp>& __a) noexcept
    { return std::less<_Tp*>()(__a.get(), nullptr); }

  template<typename _Tp1, typename _Tp2, _Lock_policy _Lp>
    inline bool
    operator>=(const __shared_ptr<_Tp1, _Lp>& __a,
	       const __shared_ptr<_Tp2, _Lp>& __b) noexcept
    { return !(__a < __b); }

  template<typename _Tp, _Lock_policy _Lp>
    inline bool
    operator>=(const __shared_ptr<_Tp, _Lp>& __a, nullptr_t) noexcept
    { return !(__a < nullptr); }

  template<typename _Tp, _Lock_policy _Lp>
    inline bool
    operator>=(nullptr_t, const __shared_ptr<_Tp, _Lp>& __a) noexcept
    { return !(nullptr < __a); }

  template<typename _Sp>
    struct _Sp_less : public binary_function<_Sp, _Sp, bool>
    {
      bool
      operator()(const _Sp& __lhs, const _Sp& __rhs) const noexcept
      {
	typedef typename _Sp::element_type element_type;
	return std::less<element_type*>()(__lhs.get(), __rhs.get());
      }
    };

  template<typename _Tp, _Lock_policy _Lp>
    struct less<__shared_ptr<_Tp, _Lp>>
    : public _Sp_less<__shared_ptr<_Tp, _Lp>>
    { };

  // 20.7.2.2.8 shared_ptr specialized algorithms.
  template<typename _Tp, _Lock_policy _Lp>
    inline void
    swap(__shared_ptr<_Tp, _Lp>& __a, __shared_ptr<_Tp, _Lp>& __b) noexcept
    { __a.swap(__b); }

  // 20.7.2.2.9 shared_ptr casts

  // The seemingly equivalent code:
  // shared_ptr<_Tp, _Lp>(static_cast<_Tp*>(__r.get()))
  // will eventually result in undefined behaviour, attempting to
  // delete the same object twice.
  /// static_pointer_cast
  template<typename _Tp, typename _Tp1, _Lock_policy _Lp>
    inline __shared_ptr<_Tp, _Lp>
    static_pointer_cast(const __shared_ptr<_Tp1, _Lp>& __r) noexcept
    { return __shared_ptr<_Tp, _Lp>(__r, static_cast<_Tp*>(__r.get())); }

  // The seemingly equivalent code:
  // shared_ptr<_Tp, _Lp>(const_cast<_Tp*>(__r.get()))
  // will eventually result in undefined behaviour, attempting to
  // delete the same object twice.
  /// const_pointer_cast
  template<typename _Tp, typename _Tp1, _Lock_policy _Lp>
    inline __shared_ptr<_Tp, _Lp>
    const_pointer_cast(const __shared_ptr<_Tp1, _Lp>& __r) noexcept
    { return __shared_ptr<_Tp, _Lp>(__r, const_cast<_Tp*>(__r.get())); }

  // The seemingly equivalent code:
  // shared_ptr<_Tp, _Lp>(dynamic_cast<_Tp*>(__r.get()))
  // will eventually result in undefined behaviour, attempting to
  // delete the same object twice.
  /// dynamic_pointer_cast
  template<typename _Tp, typename _Tp1, _Lock_policy _Lp>
    inline __shared_ptr<_Tp, _Lp>
    dynamic_pointer_cast(const __shared_ptr<_Tp1, _Lp>& __r) noexcept
    {
      if (_Tp* __p = dynamic_cast<_Tp*>(__r.get()))
	return __shared_ptr<_Tp, _Lp>(__r, __p);
      return __shared_ptr<_Tp, _Lp>();
    }

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-09-05 10:37:43  更:2021-09-05 10:38:17 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 -2024/12/27 20:31:40-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码
数据统计