C++STL中的智能指针shared_ptr以前没用过,它是不是线程安全过去也没关注过。很多说它是不安全的,也有说是安全的。线程安全的问题,简单测试是测不出,到底怎么样,需要直接看代码。
从代码看,shared_ptr是个简单包装,真正的代码从__shared_ptr开始。shared_ptr不过是换了个名字,并从__shared_ptr引出构造函数和赋值运算:
template<typename _Tp>
class shared_ptr
: public __shared_ptr<_Tp>
{
};
__shared_ptr含有2个数据元素:
template<typename _Tp>
class __shared_ptr {
_Tp* _M_ptr;
__shared_count<_Lp> _M_refcount;
};
_M_ptr是被__shared_ptr管理的对象指针,_M_refcount又是一个简单包装,内部包含一个指向_Sp_counted_base的指针:
template<_Lock_policy _Lp = __default_lock_policy>
class __shared_count
{
_Sp_counted_base<_Lp>* _M_pi;
};
这是个多态指针,实际使用时还要扩展一个指针成员:
template<typename _Ptr, _Lock_policy _Lp>
class _Sp_counted_ptr
: public _Sp_counted_base<_Lp>
{
_Ptr _M_ptr; // .... ........... .... ... .....
};
这个_M_ptr也是那个被引用计数管理的对象指针,在_Sp_counted_base及其派生类的管理范围内,如果引用计数归0,最后要销毁这个被管理的对象。但回溯到__shared_ptr 类去找到这个_M_ptr,增加了难度,所以这里又保存了一次。反过来看,这里保存的是真本,而__shared_ptr 类保存的是为了优化指针运算符重载而保留的副本。
基础类_Sp_counted_base除了扩展一个指针,根据需要,还可以扩展自定义分配器和清除器。并非所有的对象直接从new出来,有的通过自定义内存管理分配,它们会有自己专用的分配器和清除器:
template<typename _Ptr, typename _Deleter, typename _Alloc, _Lock_policy _Lp>
class _Sp_counted_deleter
: public _Sp_counted_ptr<_Ptr, _Lp>
{
typedef typename _Alloc::template
rebind<_Sp_counted_deleter>::other _My_alloc_type;
struct _My_Deleter
: public _My_alloc_type
{
_Deleter _M_del;
_My_Deleter(_Deleter __d, const _Alloc& __a)
: _My_alloc_type(__a)