目录
一、关键点解析
1、?template::value>::type>?? ?__weak_ptr(const __weak_ptr<_Tp1, _Lp>& __r) noexcept
2、lock函数
二、源码分析
一、关键点解析
1、?template<typename _Tp1, typename = typename ?? ? ? ? ? std::enable_if<std::is_convertible<_Tp1*, _Tp*>::value>::type> ?? ?__weak_ptr(const __weak_ptr<_Tp1, _Lp>& __r) noexcept
template<typename _Tp1, typename = typename
std::enable_if<std::is_convertible<_Tp1*, _Tp*>::value>::type>
__weak_ptr(const __weak_ptr<_Tp1, _Lp>& __r) noexcept
: _M_refcount(__r._M_refcount)
{ _M_ptr = __r.lock().get(); }
? ? 如果std::is_convertible<_Tp1*, _Tp*>::value是false会发生编译错误。
2、lock函数
template<typename _Tp, _Lock_policy _Lp>
class __shared_ptr
{
...
__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;
}
...
}
template<typename _Tp>
class shared_ptr : public __shared_ptr<_Tp>
{
...
// This constructor is non-standard, it is used by weak_ptr::lock().
shared_ptr(const weak_ptr<_Tp>& __r, std::nothrow_t)
: __shared_ptr<_Tp>(__r, std::nothrow) { }
...
}
__shared_ptr<_Tp, _Lp>
lock() const noexcept
{ return __shared_ptr<element_type, _Lp>(*this, std::nothrow); }
#include <memory>
#include<iostream>
int main()
{
std::shared_ptr<int> ptr(new int(2));
// std::weak_ptr<int> wptr= ptr;
// ptr=NULL;
// std::shared_ptr<int> ptr3=wptr.lock();
std::weak_ptr<int> wptr= ptr;
ptr=NULL;
std::cout<<wptr.use_count()<<std::endl;
std::shared_ptr<int> ptr3=wptr.lock();
std::cout<<ptr3.get()<<std::endl;
return 0;
}
? ? ? ?lock函数返回weak_ptr对应的shared_ptr对象,但是如果所对应的shared_ptr对象的引用计数为0,返回shared_ptr对象的_M_ptr为nullptr。
// Now that __weak_count is defined we can define this constructor:
template<_Lock_policy _Lp>
inline
__shared_count<_Lp>::
__shared_count(const __weak_count<_Lp>& __r, std::nothrow_t)
: _M_pi(__r._M_pi)
{
if (_M_pi != nullptr)
if (!_M_pi->_M_add_ref_lock_nothrow())
_M_pi = nullptr;
}
template<>
inline bool
_Sp_counted_base<_S_atomic>::
_M_add_ref_lock_nothrow()
{
// Perform lock-free add-if-not-zero operation.
_Atomic_word __count = _M_get_use_count();
do
{
if (__count == 0)
return false;
// Replace the current counter value with the old value + 1, as
// long as it's not changed meanwhile.
}
while (!__atomic_compare_exchange_n(&_M_use_count, &__count, __count + 1,
true, __ATOMIC_ACQ_REL,
__ATOMIC_RELAXED));
return true;
}
? __shared_count(const __weak_count<_Lp>& __r, std::nothrow_t)构造函数中,__weak_count所对应的use_count为0,__shared_count中的?_M_pi 为?nullptr。
二、源码分析
template<typename _Tp, _Lock_policy _Lp>
class __weak_ptr
{
public:
typedef _Tp element_type;
constexpr __weak_ptr() noexcept
: _M_ptr(0), _M_refcount()
{ }
__weak_ptr(const __weak_ptr&) noexcept = default;
__weak_ptr& operator=(const __weak_ptr&) noexcept = default;
~__weak_ptr() = default;
// The "obvious" converting constructor implementation:
//
// template<typename _Tp1>
// __weak_ptr(const __weak_ptr<_Tp1, _Lp>& __r)
// : _M_ptr(__r._M_ptr), _M_refcount(__r._M_refcount) // never throws
// { }
//
// has a serious problem.
//
// __r._M_ptr may already have been invalidated. The _M_ptr(__r._M_ptr)
// conversion may require access to *__r._M_ptr (virtual inheritance).
//
// It is not possible to avoid spurious access violations since
// in multithreaded programs __r._M_ptr may be invalidated at any point.
template<typename _Tp1, typename = typename
std::enable_if<std::is_convertible<_Tp1*, _Tp*>::value>::type>
__weak_ptr(const __weak_ptr<_Tp1, _Lp>& __r) noexcept
: _M_refcount(__r._M_refcount)
{ _M_ptr = __r.lock().get(); }
template<typename _Tp1, typename = typename
std::enable_if<std::is_convertible<_Tp1*, _Tp*>::value>::type>
__weak_ptr(const __shared_ptr<_Tp1, _Lp>& __r) noexcept
: _M_ptr(__r._M_ptr), _M_refcount(__r._M_refcount)
{ }
template<typename _Tp1>
__weak_ptr&
operator=(const __weak_ptr<_Tp1, _Lp>& __r) noexcept
{
_M_ptr = __r.lock().get();
_M_refcount = __r._M_refcount;
return *this;
}
template<typename _Tp1>
__weak_ptr&
operator=(const __shared_ptr<_Tp1, _Lp>& __r) noexcept
{
_M_ptr = __r._M_ptr;
_M_refcount = __r._M_refcount;
return *this;
}
__shared_ptr<_Tp, _Lp>
lock() const noexcept
{ return __shared_ptr<element_type, _Lp>(*this, std::nothrow); }
long
use_count() const noexcept
{ return _M_refcount._M_get_use_count(); }
bool
expired() const noexcept
{ return _M_refcount._M_get_use_count() == 0; }
template<typename _Tp1>
bool
owner_before(const __shared_ptr<_Tp1, _Lp>& __rhs) const
{ return _M_refcount._M_less(__rhs._M_refcount); }
template<typename _Tp1>
bool
owner_before(const __weak_ptr<_Tp1, _Lp>& __rhs) const
{ return _M_refcount._M_less(__rhs._M_refcount); }
void
reset() noexcept
{ __weak_ptr().swap(*this); }
void
swap(__weak_ptr& __s) noexcept
{
std::swap(_M_ptr, __s._M_ptr);
_M_refcount._M_swap(__s._M_refcount);
}
private:
// Used by __enable_shared_from_this.
void
_M_assign(_Tp* __ptr, const __shared_count<_Lp>& __refcount) noexcept
{
_M_ptr = __ptr;
_M_refcount = __refcount;
}
template<typename _Tp1, _Lock_policy _Lp1> friend class __shared_ptr;
template<typename _Tp1, _Lock_policy _Lp1> friend class __weak_ptr;
friend class __enable_shared_from_this<_Tp, _Lp>;
friend class enable_shared_from_this<_Tp>;
_Tp* _M_ptr; // Contained pointer.
__weak_count<_Lp> _M_refcount; // Reference counter.
};
// 20.7.2.3.6 weak_ptr specialized algorithms.
template<typename _Tp, _Lock_policy _Lp>
inline void
swap(__weak_ptr<_Tp, _Lp>& __a, __weak_ptr<_Tp, _Lp>& __b) noexcept
{ __a.swap(__b); }
|