先贴代码:
template<typename T>
class SharedPtr
{
public:
SharedPtr(T* ptr = 0)
:_ptr(ptr)
{
_count = new int(1);
}
SharedPtr(const SharedPtr<T>& sp)
: _ptr(sp._ptr)
, _count(sp._count)
{
++(*_count);
}
SharedPtr<T>& operator=(const SharedPtr<T>& sp)
{
if ((this != &sp) && (_ptr != sp._ptr))
{
if ((--(*_count) == 0)&&(_ptr!=NULL))
{
Release();
}
_ptr = sp._ptr;
++(*sp._count);
_count = sp._count;
}
return *this;
}
void Release()
{
if (_ptr)
{
delete _ptr;
delete _count;
_ptr = NULL;
_count = NULL;
}
}
T& operator*()
{
return *_ptr;
}
T* operator->()
{
return _ptr;
}
~SharedPtr()
{
if (--(*_count) == 0)
{
Release();
}
}
int GetCount()
{
return *_count;
}
private:
int* _count;
T* _ptr;
};
void FunTest()
{
SharedPtr<int> sp(new int);
cout << sp.GetCount() << endl;
SharedPtr<int> sp1(sp);
cout << sp1.GetCount() << endl;
SharedPtr<int> sp2;
sp2 = sp1;
cout << sp2.GetCount() << endl;
SharedPtr<int> sp4(new int);
cout << sp4.GetCount() << endl;
}
int main()
{
FunTest();
return 0;
}
采用引用计数之后,不会出现一个对象释放多次而造成的野指针的问题了,但是shared_ptr仍然存在着各种各样的问题。
线程安全问题:
shared_ptr 本身不是 100% 线程安全的。它的引用计数本身是安全且无锁的,但对象的读写则不是,因为 shared_ptr 有两个数据成员,读写操作不能原子化。shared_ptr 的线程安全级别和内建类型、标准库容器、string 一样,即:
一个 shared_ptr 实体可被多个线程同时读取;
两个的 shared_ptr 实体可以被两个线程同时写入,“析构”算写操作;
如果要从多个线程读写同一个 shared_ptr 对象,那么需要加锁。
此外,智能指针的出现,是用来管理资源的,而我们这里的shared_ptr只能用来管理动态开辟的内存空间,因此,为了维护更多的情况,我们需要定制删除器。
其次shared_ptr也会导致循环引用问题,我们需要weak_ptr来解决这个问题,后面两篇博客将解决这两个问题。