智能指针weak_ptr的核心源码实现

5 篇文章 1 订阅

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就可以编译运行了。

  • 8
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 8
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值