shared_ptr的适用场合
我们知道auto_ptr和unique_ptr的所有权唯一,释放权也唯一,但是shared_ptr是所有权不唯一,释放权是最后一个引用该资源的指针拥有,可以说所有权&释放权不唯一。
当然,更智能也意味着更多的额外消耗,shared_ptr除了需要一个指向资源的指针还要有一个指向引用计数的指针,这也就意味着为了给shared_ptr建立一个辅助类来保存计数的问题。
在使用shard_ptr时,一般与weak_ptr连用,这是为了防止相互引用的情况出现,这个我们之后会提到。
shared_ptr相关操作
这是辅助计数的类,只能被智能指针使用,所以构造函数,析构函数都是私有类型,外部不可访问。
class RefPtr
{
private:
friend class SmartPtr;
RefPtr(Point *ptr):p(ptr),count(1){ }
~RefPtr(){delete p;}
int count;
Point *p;
};
智能指针主体,最基本的功能就是让这个类的对象的行为看起来是一个指针,一个指针能做的事情,智能指针必须也能模拟成功,例如->,*,为了能够易手所有权,也要实现赋值运算符的重载,如果当前指针的所有权交给了新的一个智能指针,判定当前指针如果前置–为0时,则释放掉当前指针。并且将当前的指向的资源和新的资源指向相同即可。
class SmartPtr
{
public:
SmartPtr(Point *ptr) :rp(new RefPtr(ptr)){}
SmartPtr(const SmartPtr &sp):rp(sp.rp){++rp->count;}
//重载赋值运算符
SmartPtr& operator=(const SmartPtr& rhs)
{
++rhs.rp->count;
if (--rp->count == 0)
delete rp;
rp = rhs.rp;
return *this;
}
//重载->操作符
Point* operator->()
{
return rp->p;
}
//重载*操作符
Point& operator*()
{
return *(rp->p);
}
~SmartPtr()
{
if (--rp->count == 0)
delete rp;
else
cout << "还有" << rp->count << "个指针指向基础对象" << endl;
}
private:
RefPtr *rp;
};
shared_ptr在时间上的开销一般来自于拷贝构造和初始化中,这和auto/unique是相同的,并且shraed需要额外初始化一个辅助类或者用单例模式生成一个引用计数表,维护shared_ptr资源表的引用。