shared_ptr共享指针是C++11提供的更加可靠的智能指针,它支持拷贝赋值
shared_ptr实现的原理:通过引用计数的方式来实现多个shared_ptr对象共享一份资源。RAII的思想、重载* ->、引用计数解决浅拷贝问题。
采用mutex来保证线程安全,mutex只能保证对引用计数的安全性,对于shared_ptr管理的资源由用户去保证。
-
shared_ptr 在其内部, 给每个资源都维护了着一份计数,用来记录该份资源被几个对象共享 。
-
在 对象被销毁时 ( 也就是析构函数调用 ) ,就说明自己不使用该资源了,对象的引用计数减一。
-
如果引用计数是 0 ,就说明自己是最后一个使用该资源的对象, 必须释放该资源 ;
-
如果不是 0 ,就说明除了自己还有其他对象在使用该份资源, 不能释放该资源 ,否则其他对象就成野指针了。
namespace bite
{
template<class T>
class DeleteDef
{
public:
void operator()(T*& p)
{
if(p)
{
delete p;
p = nullptr;
}
}
};
template<class T>
class Free
{
public:
void operator()(T*& p)
{
if(p)
{
free(p);
p = nullptr;
}
}
};
template<class T>
class FClose
{
public:
void operator()(FILE*& p)
{
if(p)
{
fclose(p);
p = nullptr;
}
}
};
template<class T, class DX = DeleteDef<T>>
class shared_ptr
{
public:
shared_ptr(T* ptr = nullptr)
:_ptr(ptr)
,_pcount(nullptr)
,_pmutex(nullptr)
{
if(ptr)
{
_pcount = new int(1);
_pmutex = new mutex;
}
}
~shared_ptr()
{
_func();
}
T& operator*()
{
return *_ptr;
}
T* operator->()
{
return _ptr;
}
T* get()
{
return _ptr;
}
// 解决浅拷贝:引用计数
shared_ptr(const shared_ptr<T>& sp)
:_ptr(sp._ptr)
,_pcount(sp._pcount)
{
if(_ptr)
{
AddRef();
}
}
shared_ptr<T>& operator=(const shared_ptr<T>& sp)
{
if(this!= &sp)
{
// *thsi = sp;
// *this使用sp的共享资源
// *this可能本来就拥有资源,如果再去和sp共享一份资源,那么它的之前的资源就不用了
// *this管理资源的计数可能是 1 或者 大于 1
// *this应该对其资源的计数-1
_func();
// 让*this和sp共享资源
_ptr = sp._ptr;
_pcount = sp._pcount;
if(_ptr)
{
AddRef();
}
}
return *this;
}
int use_count()const
{
if(_pcount == nullptr)
throw bad_exception();
return *_pcount;
}
private:
void _func()
{
if(_ptr && 0 == SubRef())
{
DX() (_ptr);
_ptr = nullptr;
delete _pcount;
_pcount = nullptr;
}
}
int SubRef() // -- 是线程安全
{
_pmutex->lock();
--(*_pcount);
_pmutex->unlock();
return *_pcount;
}
void AddRef() // ++ 是线程安全
{
_pmutex->lock();
++(*_pcount);
_pmutex->unlock();
}
private:
T* _ptr;
T* _pcount;
mutex* _pmutex;
};
}
shared_ptr的缺陷:shared_ptr的缺陷是由于引用计数引起的循环引用的问题