在C++98中,我们已经有了auto_ptr(在头文件memory中)用于对资源的管理,但由于auto_ptr自身的局限制,使得auto_ptr的使用受到很大的限制,并且带来一系列“诡异”的bug,
究其原因,均是由于auto_ptr的“所有权”所致,我们注意到,对于普通的copy ctor,其形式一般为Type(const Type& rhs){...},但对于auto_ptr其copy ctor则不然,
它是auto_ptr(auto_ptr &rhs){...},之所有入参不是const的,那是因为在copy ctor之后,所有权发生了转移(同理还有operator=),即任意时刻,最多只有一个auto_ptr可以
宣称对某一原生指针具有所有权,这对于稍微复杂的场合应用来说显然是不够的(auto_ptr做为参数传递到函数中后原来的auto_ptr就作废了,继续使用原来的auto_ptr会导致错误),
因此tr1引入了shared_ptr/weak_ptr/enable_shared_from_this来解决资源的管理问题。
通过引用计数技术,每当一个weak_ptr/shared_ptr关联到同一资源时,则对应的计数器加一,当weak_ptr/shared_ptr退出作用域时,对应的计数器减一,当计数器值为0时,
则对管理的资源进行释放,我们可以通过注册资源的释放函数(deleter)来处理不同类型的资源释放。
下面根据现有的conceptgcc-boostcon/include/c++/4.3.0/tr1中的smart_ptr实现对smart_ptr进行分析,smart_ptr有shared_ptr/weak_ptr和enable_shared_from_this,
shared_ptr用于对被指向对象的所有权进行共享。被指向对象也保证会被释放(默认是调用delete,否则调用传进来的deleter),但是这将发生在最后一个指向它的shared_ptr被销毁时,
或是显式调用reset 方法时。
weak_ptr用于解决循环引用问题/使用共享资源而不共享所有权以及避免野指针。
enable_shared_from_this用于解决double deletion的问题。
首先介绍class _Sp_counted_base,_Sp_counted_base是weak_ptr/shared_ptr中的底层引用计数器的抽象父类,随着多线程编程的流行,smart_ptr的实现中考虑了多线程的情况,
因此比较复杂,为从根本上简化分析smart_ptr的实现,先去除跟多线程有关的东西,我们简化_Sp_counted_base后得到的代码如下:
class
_Sp_counted_base
...
{
public:
_Sp_counted_base(): _M_use_count(1), _M_weak_count(1) ...{ }
virtual ~_Sp_counted_base() // nothrow
...{ }
// 当_M_use_count的值为0时,调用_M_dispose
virtual void _M_dispose() = 0; // nothrow
// 当_M_weak_count的值为0时,调用_M_destroy
virtual void _M_destroy() // nothrow
...{ delete this; }
virtual void* _M_get_deleter(const std::type_info&) = 0;
// 增加_M_use_count的值
void _M_add_ref_copy()
...{ __gnu_cxx::__atomic_add_dispatch(&_M_use_count, 1); }
// 增加_M_use_count的值,同时还会检查其是否发生异常
void _M_add_ref_lock()
...{
if (__gnu_cxx::__exchange_and_add_dispatch(&_M_use_count, 1) == 0)
...{
_M_use_count = 0;
__throw_bad_weak_ptr();
}
}
// 减少_M_use_count的值,当_M_use_count为0时调用_M_dispose,同时让_M_weak_count减一并检查_M_weak_count是否也为0
// 因为对于__shared_count,一开始是让_M_use_count跟_M_weak_count都为1,所以当_M_use_count为0时也需要让_M_weak_count减1并检查其值
void _M_release() // nothrow
...{
if (__gnu_cxx::__exchange_and_add_dispatch(&_M_use_count, -1) == 1)
...{
_M_dispose();
if (__gnu_cxx::__exchange_and_add_dispatch(&_M_weak_count, -1) == 1)
_M_destroy();
}
}
// 跟_M_use_count一样
void _M_weak_add_ref() // nothrow
...{
__gnu_cxx::__atomic_add_dispatch(&_M_weak_count, 1);
}
void _M_weak_release() // nothrow
...{
if (__gnu_cxx::__exchange_and_add_dispatch(&_M_weak_count, -1) == 1)
...{
_M_destroy();
}
}
long _M_get_use_count() const // nothrow
...{
return _M_use_count;
}
private:
_Sp_counted_base(_Sp_counted_base const&);
_Sp_counted_base& operator=(_Sp_counted_base const&);
_Atomic_word _M_use_count; // #shared
_Atomic_word _M_weak_count; // #weak + (#shared != 0)
}
;
// __weak_count/__shared_count中都有_Sp_counted_base*成员,其实际类型为_Sp_counted_base_impl
// _Sp_counted_base_impl总共有4个成员,用于共享所有权计数的_M_use_count,共享所有树计数和不共享所有权计数的总和_M_weak_count,原生指针_M_ptr,deleter _M_del
template
<
typename _Ptr, typename _Deleter
>
class
_Sp_counted_base_impl :
public
_Sp_counted_base
...
{
public:
_Sp_counted_base_impl(_Ptr __p, _Deleter __d) : _M_ptr(__p), _M_del(__d) ...{ }
// 当共享计数_M_use_count的值为0时,调用其deleter对资源进行释放
virtual void _M_dispose() // nothrow
...{
_M_del(_M_ptr);
}
// 返回deleter
virtual void* _M_get_deleter(const std::type_info& __ti)
...{
return __ti == typeid(_Deleter) ? &_M_del : 0;
}
private:
_Sp_counted_base_impl(const _Sp_counted_base_impl&);
_Sp_counted_base_impl& operator=(const _Sp_counted_base_impl&);
_Ptr _M_ptr; // 原生指针
_Deleter _M_del; // deleter
}
;
// 前向声明__weak_count,__weak_count可以访问__shared_count中的所有成员
class __weak_count;
// __shared_count的构造方法有:使用默认构造函数构造空的;通过原生指针构造;通过auto_ptr构造;通过weak_count构造;通过拷贝函数构造;
class
__shared_count
...
{
public:
__shared_count() : _M_pi(0) // nothrow
...{ }
// 构造完成后其_M_use_count和_M_weak_count的值均为1
template<typename _Ptr, typename _Deleter>
__shared_count(_Ptr __p, _Deleter __d) : _M_pi(0)
...{
try
...{
_M_pi = new _Sp_counted_base_impl<_Ptr, _Deleter>(__p, __d);
}
catch(...)
...{
// 如果构造失败,则调用deleter释放资源
__d(__p);
__throw_exception_again;
}
}
// 通过auto_ptr构造的,其deleter均为delete
template<typename _Tp> explicit __shared_count(std::auto_ptr<_Tp>& __r) :
_M_pi(new _Sp_counted_base_impl<_Tp*, _Sp_deleter<_Tp> >(__r.get(), _Sp_deleter<_Tp>()))
...{
__r.release();
}
// 从__weak_count构造__shared_count,如果构造的__shared_count._M_use_count为0,抛出bad_weak_ptr,如果_M_pi为0,也抛出bad_weak_ptr
// 后面的enable_shared_from_this就是从weak_count进行构造
explicit __shared_count(const __weak_count& __r): _M_pi(__r._M_pi)
...{
if (_M_pi != 0)
_M_pi->_M_add_ref_lock();
else
__throw_bad_weak_ptr();
}
~__shared_count() // nothrow
...{
if (_M_pi != 0)
_M_pi->_M_release();
}
__shared_count(const __shared_count& __r) : _M_pi(__r._M_pi)
...{
if (_M_pi != 0)
_M_pi->_M_add_ref_copy();
}
__shared_count& operator=(const __shared_count& __r)
...{
_Sp_counted_base *__tmp = __r._M_pi;
if (__tmp != _M_pi)
...{
if (__tmp != 0)
__tmp->_M_add_ref_copy();
if (_M_pi != 0)
_M_pi->_M_release();
_M_pi = __tmp;
}
return *this;
}
void _M_swap(__shared_count& __r)
...{
_Sp_counted_base *__tmp = __r._M_pi;
__r._M_pi = _M_pi;
_M_pi = __tmp;
}
long _M_get_use_count() const
...{
return _M_pi != 0 ? _M_pi->_M_get_use_count() : 0;
}
bool _M_unique() const
...{
return this->_M_get_use_count() == 1;
}
friend inline bool operator==(const __shared_count& __a, const __shared_count& __b)
...{
return __a._M_pi == __b._M_pi;
}
friend inline bool operator<(const __shared_count& __a, const __shared_count& __b)
...{
return std::less<_Sp_counted_base*>()(__a._M_pi, __b._M_pi);
}
void* _M_get_deleter(const std::type_info& __ti) const
...{
return _M_pi ? _M_pi->_M_get_deleter(__ti) : 0;
}
private:
friend class __weak_count;
_Sp_counted_base *_M_pi;
}
;
// __shared_count也是__weak_count的友元类,可以访问__weak_count中的任何成员
// __weak_count的构造只能通过默认构造函数构造空的,通过__shared_count构造,通过拷贝函数构造
class
__weak_count
...
{
public:
__weak_count() : _M_pi(0)
...{ }
__weak_count(const __shared_count& __r) : _M_pi(__r._M_pi)
...{
if (_M_pi != 0)
_M_pi->_M_weak_add_ref();
}
__weak_count(const __weak_count& __r) : _M_pi(__r._M_pi)
...{
if (_M_pi != 0)
_M_pi->_M_weak_add_ref();
}
~__weak_count()
...{
if (_M_pi != 0)
_M_pi->_M_weak_release();
}
__weak_count& operator=(const __shared_count& __r)
...{
_Sp_counted_base *__tmp = __r._M_pi;
if (__tmp != 0)
__tmp->_M_weak_add_ref();
if (_M_pi != 0)
_M_pi->_M_weak_release();
_M_pi = __tmp;
return *this;
}
__weak_count& operator=(const __weak_count& __r)
...{
_Sp_counted_base *__tmp = __r._M_pi;
if (__tmp != 0)
__tmp->_M_weak_add_ref();
if (_M_pi != 0)
_M_pi->_M_weak_release();
_M_pi = __tmp;
return *this;
}
void _M_swap(__weak_count& __r)
...{
_Sp_counted_base* __tmp = __r._M_pi;
__r._M_pi = _M_pi;
_M_pi = __tmp;
}
long _M_get_use_count() const
...{
return _M_pi != 0 ? _M_pi->_M_get_use_count() : 0;
}
friend inline bool operator==(const __weak_count& __a, const __weak_count& __b)
...{
return __a._M_pi == __b._M_pi;
}
friend inline bool operator<(const __weak_count& __a, const __weak_count& __b)
...{
return std::less<_Sp_counted_base*>()(__a._M_pi, __b._M_pi);
}
private:
friend class __shared_count;
_Sp_counted_base *_M_pi;
}
;
// 前向声明
template<typename _Tp>
class __shared_ptr;
template<typename _Tp>
class __weak_ptr;
template<typename _Tp>
class __enable_shared_from_this;
template<typename _Tp>
class shared_ptr;
template<typename _Tp>
class weak_ptr;
template<typename _Tp>
class enable_shared_from_this;
// 函数的优先级:如果类有友元函数,则优先调用友元函数;否则调用全局函数
// __shared_ptr时会调用__enable_shared_from_this_helper,如果是派生自__enable_shared_from_this类的,那么有友元函数,调用它
// 否则调用全局函数,全局函数为空,什么都不干
template<typename _Tp1, typename _Tp2>
void __enable_shared_from_this_helper(const __shared_count&, const __enable_shared_from_this<_Tp1>*, const _Tp2*);
template<>
inline void __enable_shared_from_this_helper(const __shared_count&, ...)
{ }
template<typename _Tp1, typename _Tp2>
void __enable_shared_from_this_helper(const __shared_count&, const enable_shared_from_this<_Tp1>*, const _Tp2*);
struct __static_cast_tag { };
struct __const_cast_tag { };
struct __dynamic_cast_tag { };
template
<
typename _Tp
>
class
__shared_ptr
...
{
public:
typedef _Tp element_type;
// 构造空的__shared_ptr
__shared_ptr() : _M_ptr(0), _M_refcount()
...{ }
// 根据原生指针构造__shared_ptr,对原生指针的资源释放使用delete
// 如果不是enable_shared_from_this,完成后_M_use_count为1,_M_weak_count为1
template<typename _Tp1>
explicit __shared_ptr(_Tp1* __p) : _M_ptr(__p), _M_refcount(__p, _Sp_deleter<_Tp1>())
...{
// 如果类是通过派生自__enable_shared_from_this,那么就有__enable_shared_from_this_helper函数的实现,将调用对应的__enable_shared_from_this_helper,
// __enable_shared_from_this_helper设置_M_weak_this,使得所有权个数(_M_use_count)加1,而weak_count(_M_weak_count)个数不变
// 否则调用__enable_shared_from_this_helper(const __shared_count&, ...),该函数为空
__enable_shared_from_this_helper(_M_refcount, __p, __p);
}
// 根据原生指针及删除对象构造__shared_ptr,对原生指针的资源的释放使用删除对象来进行
// 如果不是enable_shared_from_this,完成后_M_use_count为1,_M_weak_count为1
template<typename _Tp1, typename _Deleter>
__shared_ptr(_Tp1* __p, _Deleter __d) : _M_ptr(__p), _M_refcount(__p, __d)
...{
// 同上
__enable_shared_from_this_helper(_M_refcount, __p, __p);
}
// 从auto_ptr构造__shared_ptr
template<typename _Tp1>
explicit __shared_ptr(std::auto_ptr<_Tp1>& __r) : _M_ptr(__r.get()), _M_refcount()
...{
_Tp1* __tmp = __r.get();
_M_refcount = __shared_count(__r);
__enable_shared_from_this_helper(_M_refcount, __tmp, __tmp);
}
// copy ctor,完成后_M_use_count加1,_M_weak_count不变
template<typename _Tp1>
__shared_ptr(const __shared_ptr<_Tp1>& __r) : _M_ptr(__r._M_ptr), _M_refcount(__r._M_refcount)
...{ }
// 从__weak_ptr构造__shared_ptr,完成后_M_use_count加1,_M_weak_count不变--enable_shared_from_this对应于这种情况
template<typename _Tp1>
explicit __shared_ptr(const __weak_ptr<_Tp1>& __r) : _M_refcount(__r._M_refcount)
...{
_M_ptr = __r._M_ptr;
}
// 从不同类型的__shared_ptr构造__shared_ptr,进行static_cast
template<typename _Tp1>
__shared_ptr(const __shared_ptr<_Tp1>& __r, __static_cast_tag) : _M_ptr(static_cast<element_type*>(__r._M_ptr)), _M_refcount(__r._M_refcount)
...{ }
// 从不同类型的__shared_ptr构造__shared_ptr,进行const_cast
template<typename _Tp1>
__shared_ptr(const __shared_ptr<_Tp1>& __r, __const_cast_tag) : _M_ptr(const_cast<element_type*>(__r._M_ptr)), _M_refcount(__r._M_refcount)
...{ }
// 从不同类型的__shared_ptr构造__shared_ptr,进行dynamic_cast
template<typename _Tp1>
__shared_ptr(const __shared_ptr<_Tp1>& __r, __dynamic_cast_tag) : _M_ptr(dynamic_cast<element_type*>(__r._M_ptr)), _M_refcount(__r._M_refcount)
...{
if (_M_ptr == 0) // need to allocate new counter -- the cast failed
_M_refcount = __shared_count();
}
template<typename _Tp1>
__shared_ptr& operator=(const __shared_ptr<_Tp1>& __r)
...{
_M_ptr = __r._M_ptr;
_M_refcount = __r._M_refcount;
return *this;
}
// 从auto_ptr赋值得到
template<typename _Tp1> __shared_ptr& operator=(std::auto_ptr<_Tp1>& __r)
...{
__shared_ptr(__r).swap(*this);
return *this;
}
// 重置__shared_ptr为空
void reset()
...{
__shared_ptr().swap(*this);
}
// 重置__shared_ptr
template<typename _Tp1> void reset(_Tp1* __p)
...{
// Catch self-reset errors.
_GLIBCXX_DEBUG_ASSERT(__p == 0 || __p != _M_ptr);
__shared_ptr(__p).swap(*this);
}
// 重置__shared_ptr
template<typename _Tp1, typename _Deleter> void reset(_Tp1* __p, _Deleter __d)
...{
__shared_ptr(__p, __d).swap(*this);
}
typename add_reference<_Tp>::type operator*() const
...{
_GLIBCXX_DEBUG_ASSERT(_M_ptr != 0);
return *_M_ptr;
}
_Tp* operator->() const
...{
_GLIBCXX_DEBUG_ASSERT(_M_ptr != 0);
return _M_ptr;
}
_Tp* get() const
...{
return _M_ptr;
}
private:
// Implicit conversion to "bool"
typedef _Tp* __shared_ptr::*__unspecified_bool_type;
public:
operator __unspecified_bool_type() const // never throws
...{
return _M_ptr == 0 ? 0 : &__shared_ptr::_M_ptr;
}
// 是否只有一个shared_ptr拥有当前资源的所有权
bool unique() const
...{
return _M_refcount._M_unique();
}
long use_count() const
...{
return _M_refcount._M_get_use_count();
}
void swap(__shared_ptr<_Tp>& __other)
...{
std::swap(_M_ptr, __other._M_ptr);
_M_refcount._M_swap(__other._M_refcount);
}
private:
void* _M_get_deleter(const std::type_info& __ti) const
...{
return _M_refcount._M_get_deleter(__ti);
}
template<typename _Tp1> bool _M_less(const __shared_ptr<_Tp1>& __rhs) const
...{
return _M_refcount < __rhs._M_refcount;
}
template<typename _Tp1> friend class __shared_ptr;
template<typename _Tp1> friend class __weak_ptr;
template<typename _Del, typename _Tp1> friend _Del* get_deleter(const __shared_ptr<_Tp1>&);
// Friends injected into enclosing namespace and found by ADL:
template<typename _Tp1> friend inline bool operator==(const __shared_ptr& __a, const __shared_ptr<_Tp1>& __b)
...{
return __a.get() == __b.get();
}
template<typename _Tp1> friend inline bool operator!=(const __shared_ptr& __a, const __shared_ptr<_Tp1>& __b)
...{
return __a.get() != __b.get();
}
template<typename _Tp1> friend inline bool operator<(const __shared_ptr& __a, const __shared_ptr<_Tp1>& __b)
...{
return __a._M_less(__b);
}
_Tp *_M_ptr; // 资源指针
__shared_count _M_refcount; // 与该资源相关的计数器
}
;
template
<
typename _Tp
>
inline
void
swap(__shared_ptr
<
_Tp
>&
__a, __shared_ptr
<
_Tp
>&
__b)
...
{
__a.swap(__b);
}
template
<
typename _Tp, typename _Tp1
>
__shared_ptr
<
_Tp
>
static_pointer_cast(
const
__shared_ptr
<
_Tp1
>&
__r)
...
{
return __shared_ptr<_Tp>(__r, __static_cast_tag());
}
template
<
typename _Tp, typename _Tp1
>
__shared_ptr
<
_Tp
>
const_pointer_cast(
const
__shared_ptr
<
_Tp1
>&
__r)
...
{
return __shared_ptr<_Tp>(__r, __const_cast_tag());
}
template
<
typename _Tp, typename _Tp1
>
__shared_ptr
<
_Tp
>
dynamic_pointer_cast(
const
__shared_ptr
<
_Tp1
>&
__r)
...
{
return __shared_ptr<_Tp>(__r, __dynamic_cast_tag());
}
template
<
typename _Ch, typename _Tr, typename _Tp
>
std::basic_ostream
<
_Ch, _Tr
>&
operator
<<
(std::basic_ostream
<
_Ch, _Tr
>&
__os,
const
__shared_ptr
<
_Tp
>&
__p)
...
{
__os << __p.get();
return __os;
}
template
<
typename _Del, typename _Tp
>
inline _Del
*
get_deleter(
const
__shared_ptr
<
_Tp
>&
__p)
...
{
return static_cast<_Del*>(__p._M_get_deleter(typeid(_Del)));
}
// __weak_ptr只能通过默认构造函数构造/__weak_ptr进行拷贝构造/__shared_ptr进行构造
template
<
typename _Tp
>
class
__weak_ptr
...
{
public:
typedef _Tp element_type;
// default ctor,构造空的__weak_ptr
__weak_ptr() : _M_ptr(0), _M_refcount()
...{ }
// copy ctor
template<typename _Tp1>
__weak_ptr(const __weak_ptr<_Tp1>& __r) : _M_refcount(__r._M_refcount)
...{
_M_ptr = __r.lock().get();
}
// 从__shared_ptr构造__weak_ptr,完成后_M_use_count不变,_M_weak_count加1
template<typename _Tp1>
__weak_ptr(const __shared_ptr<_Tp1>& __r) : _M_ptr(__r._M_ptr), _M_refcount(__r._M_refcount)
...{ }
template<typename _Tp1>
__weak_ptr& operator=(const __weak_ptr<_Tp1>& __r)
...{
_M_ptr = __r.lock().get();
_M_refcount = __r._M_refcount;
return *this;
}
template<typename _Tp1>
__weak_ptr& operator=(const __shared_ptr<_Tp1>& __r)
...{
_M_ptr = __r._M_ptr;
_M_refcount = __r._M_refcount;
return *this;
}
// 如果__shared_ptr的引用计数为0,则返回空的__shared_ptr,否则返回由__weak_ptr构造的__shared_ptr
__shared_ptr<_Tp>
lock() const
...{
return expired() ? __shared_ptr<element_type>() : __shared_ptr<element_type>(*this);
}
long use_count() const
...{
return _M_refcount._M_get_use_count();
}
bool expired() const
...{
return _M_refcount._M_get_use_count() == 0;
}
void reset()
...{
__weak_ptr().swap(*this);
}
void swap(__weak_ptr& __s)
...{
std::swap(_M_ptr, __s._M_ptr);
_M_refcount._M_swap(__s._M_refcount);
}
private:
// 被__enable_shared_from_this所调用
// 完成后_M_use_count不变,_M_weak_count加1
void _M_assign(_Tp* __ptr, const __shared_count& __refcount)
...{
_M_ptr = __ptr;
_M_refcount = __refcount;
}
template<typename _Tp1>
bool _M_less(const __weak_ptr<_Tp1>& __rhs) const
...{
return _M_refcount < __rhs._M_refcount;
}
template<typename _Tp1> friend class __shared_ptr;
friend class __enable_shared_from_this<_Tp>;
friend class enable_shared_from_this<_Tp>;
// Friend injected into namespace and found by ADL.
template<typename _Tp1> friend inline bool operator<(const __weak_ptr& __lhs, const __weak_ptr<_Tp1>& __rhs)
...{
return __lhs._M_less(__rhs);
}
_Tp* _M_ptr; // 资源指针
__weak_count _M_refcount; // 与资源指针关联的计数器
}
;
template
<
typename _Tp
>
inline
void
swap(__weak_ptr
<
_Tp
>&
__a, __weak_ptr
<
_Tp
>&
__b)
...
{
__a.swap(__b);
}
template
<
typename _Tp
>
class
__enable_shared_from_this
...
{
protected:
__enable_shared_from_this() ...{ }
__enable_shared_from_this(const __enable_shared_from_this&) ...{ }
__enable_shared_from_this& operator=(const __enable_shared_from_this&)
...{
return *this;
}
~__enable_shared_from_this() ...{ }
public:
__shared_ptr<_Tp> shared_from_this()
...{
return __shared_ptr<_Tp>(this->_M_weak_this);
}
__shared_ptr<const _Tp> shared_from_this() const
...{
return __shared_ptr<const _Tp>(this->_M_weak_this);
}
private:
template<typename _Tp1> void _M_weak_assign(_Tp1* __p, const __shared_count& __n) const
...{
_M_weak_this._M_assign(__p, __n);
}
template<typename _Tp1>
friend void __enable_shared_from_this_helper(const __shared_count& __pn, const __enable_shared_from_this* __pe, const _Tp1* __px)
...{
if (__pe != 0)
__pe->_M_weak_assign(const_cast<_Tp1*>(__px), __pn);
}
mutable __weak_ptr<_Tp> _M_weak_this;
}
;
template
<
typename _Tp
>
class
shared_ptr :
public
__shared_ptr
<
_Tp
>
...
{
public:
shared_ptr() : __shared_ptr<_Tp>() ...{ }
template<typename _Tp1>
explicit shared_ptr(_Tp1* __p) : __shared_ptr<_Tp>(__p) ...{ }
template<typename _Tp1, typename _Deleter>
shared_ptr(_Tp1* __p, _Deleter __d) : __shared_ptr<_Tp>(__p, __d) ...{ }
template<typename _Tp1>
shared_ptr(const shared_ptr<_Tp1>& __r) : __shared_ptr<_Tp>(__r) ...{ }
template<typename _Tp1>
explicit shared_ptr(const weak_ptr<_Tp1>& __r) : __shared_ptr<_Tp>(__r) ...{ }
template<typename _Tp1>
explicit shared_ptr(std::auto_ptr<_Tp1>& __r) : __shared_ptr<_Tp>(__r) ...{ }
template<typename _Tp1>
shared_ptr(const shared_ptr<_Tp1>& __r, __static_cast_tag) : __shared_ptr<_Tp>(__r, __static_cast_tag()) ...{ }
template<typename _Tp1>
shared_ptr(const shared_ptr<_Tp1>& __r, __const_cast_tag) : __shared_ptr<_Tp>(__r, __const_cast_tag()) ...{ }
template<typename _Tp1>
shared_ptr(const shared_ptr<_Tp1>& __r, __dynamic_cast_tag) : __shared_ptr<_Tp>(__r, __dynamic_cast_tag()) ...{ }
template<typename _Tp1>
shared_ptr& operator=(const shared_ptr<_Tp1>& __r) // never throws
...{
this->__shared_ptr<_Tp>::operator=(__r);
return *this;
}
template<typename _Tp1>
shared_ptr& operator=(std::auto_ptr<_Tp1>& __r)
...{
this->__shared_ptr<_Tp>::operator=(__r);
return *this;
}
}
;
template
<
typename _Tp, typename _Tp1
>
shared_ptr
<
_Tp
>
static_pointer_cast(
const
shared_ptr
<
_Tp1
>&
__r)
...
{
return shared_ptr<_Tp>(__r, __static_cast_tag());
}
template
<
typename _Tp, typename _Tp1
>
shared_ptr
<
_Tp
>
const_pointer_cast(
const
shared_ptr
<
_Tp1
>&
__r)
...
{
return shared_ptr<_Tp>(__r, __const_cast_tag());
}
template
<
typename _Tp, typename _Tp1
>
shared_ptr
<
_Tp
>
dynamic_pointer_cast(
const
shared_ptr
<
_Tp1
>&
__r)
...
{
return shared_ptr<_Tp>(__r, __dynamic_cast_tag());
}
template
<
typename _Tp
>
class
weak_ptr :
public
__weak_ptr
<
_Tp
>
...
{
public:
weak_ptr() : __weak_ptr<_Tp>() ...{ }
template<typename _Tp1>
weak_ptr(const weak_ptr<_Tp1>& __r) : __weak_ptr<_Tp>(__r) ...{ }
template<typename _Tp1>
weak_ptr(const shared_ptr<_Tp1>& __r) : __weak_ptr<_Tp>(__r) ...{ }
template<typename _Tp1>
weak_ptr& operator=(const weak_ptr<_Tp1>& __r) // never throws
...{
this->__weak_ptr<_Tp>::operator=(__r);
return *this;
}
template<typename _Tp1>
weak_ptr& operator=(const shared_ptr<_Tp1>& __r) // never throws
...{
this->__weak_ptr<_Tp>::operator=(__r);
return *this;
}
shared_ptr<_Tp> lock() const // never throws
...{
return this->expired() ? shared_ptr<_Tp>() : shared_ptr<_Tp>(*this);
}
}
;
template
<
typename _Tp
>
class
enable_shared_from_this
...
{
protected:
enable_shared_from_this() ...{ }
enable_shared_from_this(const enable_shared_from_this&) ...{ }
enable_shared_from_this& operator=(const enable_shared_from_this&)
...{
return *this;
}
~enable_shared_from_this() ...{ }
public:
// 使其_M_use_count加1
shared_ptr<_Tp> shared_from_this()
...{
return shared_ptr<_Tp>(this->_M_weak_this);
}
// 使其_M_use_count加1
shared_ptr<const _Tp> shared_from_this() const
...{
return shared_ptr<const _Tp>(this->_M_weak_this);
}
private:
template<typename _Tp1>
void _M_weak_assign(_Tp1* __p, const __shared_count<>& __n) const
...{
_M_weak_this._M_assign(__p, __n);
}
// 使其_M_weak_count加1
template<typename _Tp1>
friend void __enable_shared_from_this_helper(const __shared_count<>& __pn, const enable_shared_from_this* __pe, const _Tp1* __px)
...{
if (__pe != 0)
__pe->_M_weak_assign(const_cast<_Tp1*>(__px), __pn);
}
mutable weak_ptr<_Tp> _M_weak_this;
}
;
// enable_shared_from_this存在的理由是对于以下代码,将出现double deletion,这是致命的
// 引自Stephan T. Lavavej的shared_ptr.pptx
struct
Ansible
...
{
shared_ptr<Ansible> get_shared() ...{
shared_ptr<Ansible> ret(this);
return ret;
}
}
;
int
main()
...
{
shared_ptr<Ansible> a(new Ansible);
Ansible& r = *a;
shared_ptr<Ansible> b = r.get_shared();
}
// 而通过enable_shared_from_this,可以避免这个问题
struct
Ansible
:
public
enable_shared_from_this
<
Ansible
>
...
{ }
;
int
main()
...
{
shared_ptr<Ansible> a(new Ansible);
Ansible& r = *a;
shared_ptr<Ansible> b = r.shared_from_this();
}
跟前面代码分析的一样,通过enable_shared_from_this,构造b时增加_M_use_count和_M_weak_count的值,因此不会出现double delete的情况
下面给出smart_ptr的示例代码:
1
. shared_ptr
A.
...
{
FILE*fptr = fopen("some_path", "mode");
shared_ptr<FILE> Fptr(fptr, fclose);
...// 使用Fptr,退出作用域时释放fptr
}
B.
...
{
struct Foo...{
shared_ptr<FILE> m_fptr;
Foo()...{}
Foo(const char *filename, const char *mode):m_fptr(fopen(filename, mode), fclose)...{}
};
Foo f1("some_path", "mode");
// use f1
Foo f2(f1);
// use f2
Foo f3;
f3 = f1;
// use f3
// f1,f2,f3都拥有同一文件的所有权,只有退出作用域时才会释放资源
}
C.把share_ptr
<
Type
>
插入到容器中
2
. weak_ptr
解决循环引用(circular reference)的问题,参考《
Smart Pointers to boost your code》
《A beginner's introduction to the smart pointers provided by the boost library》
By
peterchen
...
{
struct CSample...{};
struct CDad;
struct CChild;
typedef shared_ptr<CDad> CDadPtr;
typedef shared_ptr<CChild> CChildPtr;
struct CDad : public CSample
...{
CChildPtr myBoy;
};
struct CChild : public CSample
...{
CDadPtr myDad;
};
CDadPtr dad(new CDad);
CChildPtr child(new CChild);
dad->myBoy = child;
child->myDad = dad;
child.reset();
// dad还引用到CDad对象,而CDad对象引用到CChild对象
dad.reset();
// 此时dad和child的引用计数器的值均为1,出现了内存泄露
}
通过weak_ptr的解决办法如下:
...
{
struct CSample...{};
struct CDad;
struct CChild;
typedef shared_ptr<CDad> CDadPtr;
typedef shared_ptr<CChild> CChildPtr;
struct CDad : public CSample
...{
weak_ptr<CChild> myBoy;
};
struct CChild : public CSample
...{
weak_ptr<CDad> myDad;
};
CDadPtr dad(new CDad);
CChildPtr child(new CChild);
dad->myBoy = child;
child->myDad = dad;
child.reset();
dad.reset();
}
3
.enable_shared_from_this的例子见Stephan T. Lavavej的shared_ptr.pptx,即上面的代码
通过上面的源码分析,我实现一个迷你版本的my_shared_ptr,不考虑多线程情况,源码如下:
template
<
typename ClassType, typename Deleter
>
class
my_shared_ptr
...
{
private:
ClassType *m_ptr;
Deleter m_deleter; // Deleter必须有default ctor和copy ctor,对于非类类型,具有bitwise copy语义
int *m_refCount;
public:
my_shared_ptr(): m_ptr(0), m_refCount(0)...{}
my_shared_ptr(ClassType *ptr, Deleter deleter = Deleter()): m_ptr(ptr), m_deleter(deleter)
...{
m_refCount = new int(1);
}
~my_shared_ptr()
...{
*m_refCount -= 1;
if (*m_refCount == 0) ...{
m_deleter(m_ptr);
delete m_refCount;
}
}
ClassType* operator->()
...{
return m_ptr;
}
ClassType& operator*()
...{
return *m_ptr;
}
my_shared_ptr(const my_shared_ptr &rhs)
...{
m_ptr = rhs.m_ptr;
m_deleter = rhs.m_deleter;
m_refCount = rhs.m_refCount;
if( m_refCount )
...{
*m_refCount += 1;
}
}
template<typename OtherClassType, typename OtherDeleter>
my_shared_ptr& operator=(const my_shared_ptr<OtherClassType, OtherDeleter> &rhs)
...{
if (this != &rhs) ...{
*m_refCount -= 1;
if (*m_refCount == 0) ...{
m_deleter(m_ptr);
delete m_refCount;
}
m_ptr = rhs.m_ptr;
m_deleter = rhs.m_deleter;
m_refCount = rhs.m_refCount;
if( m_refCount )
...{
*m_refCount += 1;
}
return *this;
}
return *this;
}
operator ClassType*()
...{
return m_ptr;
}
}
;
顺带说一下,在网上翻资料的时候看到智能指针使用了特殊的observer模式,确实如此。