weakptr的作为弱引用指针,其实现依赖于counter的计数器类和share_ptr的赋值,构造,所以需要把counter和share_ptr也简单实现一下。
counter对象的目地就是用来申请一个块内存来存引用基数,简单实现如下:
class Counter
{
public:
Counter():s(0),w(0){};
int s;
int w;
};
s是share_ptr的引用计数,w是weak_ptr的引用计数,当w为0时,删除Counter对象。
share_ptr的简单实现如下:
template<class T> class WeakPtr;//为了用weak_ptr的lock(),来生成share_ptr用,需要拷贝构造用
template<class T>
class SharePtr
{
public:
SharePtr(T* p=0)
:_ptr(p){
cnt=new Counter();
if(p)
cnt->s=1;
cout<<"in construct "<<cnt->s<<endl;
}
~SharePtr()
{
release();
}
SharePtr(SharePtr<T> const &s)
{
cout<<"in copy con"<<endl;
_ptr=s._ptr;
(s.cnt)->s++;
cout<<"copy construct"<<(s.cnt)->s<<endl;
cnt=s.cnt;
}
SharePtr(WeakPtr<T> const &w)//为了用weak_ptr的lock(),来生成share_ptr用,需要拷贝构造用
{
cout<<"in w copy con "<<endl;
_ptr=w._ptr;
(w.cnt)->s++;
cout<<"copy w construct"<<(w.cnt)->s<<endl;
cnt=w.cnt;
}
SharePtr<T>& operator=(SharePtr<T> &s)
{
if(this != &s)
{
release();
(s.cnt)->s++;
cout<<"assign construct "<<(s.cnt)->s<<endl;
cnt=s.cnt;
_ptr=s._ptr;
}
return *this;
}
T& operator *()
{
return *_ptr;
}
T* operator ->()
{
return _ptr;
}
friend class WeakPtr<T>; //方便weak_ptr与share_ptr设置引用计数和赋值。
private:
void release()
{
cnt->s--;
cout<<"release "<<cnt->s<<endl;
if(cnt->s <1)
{
delete _ptr;
if(cnt->w <1)
{
delete cnt;
cnt=NULL;
}
}
}
T* _ptr;
Counter* cnt;
};
share_ptr的给出的函数接口为:构造,拷贝构造,赋值,解引用。通过release来在引用计数为0的时候删除_ptr和cnt的内存。
那么最后可以给出weak_ptr的实现,如下:
template<class T>
class WeakPtr
{
public://给出默认构造和拷贝构造,其中拷贝构造不能有从原始指针进行构造
WeakPtr()
{
_ptr=0;
cnt=0;
}
WeakPtr(SharePtr<T>& s):
_ptr(s._ptr),cnt(s.cnt)
{
cout<<"w con s"<<endl;
cnt->w++;
}
WeakPtr(WeakPtr<T>& w):
_ptr(w._ptr),cnt(w.cnt)
{
cnt->w++;
}
~WeakPtr()
{
release();
}
WeakPtr<T>& operator =(WeakPtr<T> & w)
{
if(this != &w)
{
release();
cnt=w.cnt;
cnt->w++;
_ptr=w._ptr;
}
return *this;
}
WeakPtr<T>& operator =(SharePtr<T> & s)
{
cout<<"w = s"<<endl;
release();
cnt=s.cnt;
cnt->w++;
_ptr=s._ptr;
return *this;
}
SharePtr<T> lock()
{
return SharePtr<T>(*this);
}
bool expired()
{
if(cnt)
{
if(cnt->s >0)
{
cout<<"empty "<<cnt->s<<endl;
return false;
}
}
return true;
}
friend class SharePtr<T>;//方便weak_ptr与share_ptr设置引用计数和赋值。
private:
void release()
{
if(cnt)
{
cnt->w--;
cout<<"weakptr release"<<cnt->w<<endl;
if(cnt->w <1&& cnt->s <1)
{
//delete cnt;
cnt=NULL;
}
}
}
T* _ptr;
Counter* cnt;
};
share_ptr的一般接口是,通过share_ptr来构造,通过expired函数检查原始指针是否为空,lock来转化为share_ptr。
测试代码如下:
class parent;
class child;
class parent
{
public:
// SharePtr<child> ch;
WeakPtr<child> ch;
};
class child
{
public:
SharePtr<parent> pt;
};
int main()
{
//SharePtr<parent> ft(new parent());
//SharePtr<child> son(new child());
//ft->ch=son;
//son->pt=ft;
//SharePtr<child> son2=(ft->ch).lock();
SharePtr<int> i;
WeakPtr<int> wi(i);
cout<<wi.expired()<<endl;
return 0;
}
通过打开注释,可以模拟share_ptr的经典的循环引用的案例,也可以检查指针是否为空。
完整代码,加入iostream头文件和std的namespace就可以编译运行了。