share_ptr和weak_ptr的核心实现

C++ 专栏收录该内容
19 篇文章 0 订阅

weakptr的作为弱引用指针,其实现依赖于counter的计数器类和share_ptr的赋值,构造,所以先把counter和share_ptr简单实现

Counter简单实现

class Counter
{
public:
    Counter() : s(0), w(0){};
    int s;	//share_ptr的引用计数
    int w;	//weak_ptr的引用计数
};

counter对象的目地就是用来申请一个块内存来存引用基数,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();  // 新建Counter对象
        if (p)  // 对象指针不为nullptr
            cnt->s = 1;  // 引用计数器初值
        cout << "in construct " << cnt->s << endl;
    }
    ~SharePtr()  // 析构函数
    {
        release();  // 释放所管理对象,如果引用计数为0则回收所管理对象对应内存空间
    }

    SharePtr(SharePtr<T> const &s)  // 拷贝构造函数
    {
        cout << "in copy con" << endl;
        _ptr = s._ptr;  // 复制对象指针
        (s.cnt)->s++;  // 原share_ptr对象引用计数自增
        cout << "copy construct" << (s.cnt)->s << endl;
        cnt = s.cnt;  // 复制Counter对象
    }
    SharePtr(WeakPtr<T> const &w) //为了用weak_ptr的lock(),来生成share_ptr用,需要拷贝构造用
    {
        cout << "in w copy con " << endl;
        _ptr = w._ptr;  // 复制weak_ptr管理对象的指针
        (w.cnt)->s++;  // 引用计数自增
        cout << "copy w  construct" << (w.cnt)->s << endl;
        cnt = w.cnt;  // 复制Count对象
    }
    SharePtr<T> &operator=(SharePtr<T> &s)  // =运算符重载
    {
        if (this != &s)  // 防止自我引用,导致引用计数增加
        {
            release();  // 先释放原管理对象的所有权
            (s.cnt)->s++;  // 引用计数自增
            cout << "assign construct " << (s.cnt)->s << endl;
            cnt = s.cnt;  // 复制Count对象
            _ptr = s._ptr;  // 复制新管理对象的指针
        }
        return *this;
    }
    T &operator*()  // 重载*运算符
    {
        return *_ptr;
    }
    T *operator->()  // 重载->运算符
    {
        return _ptr;
    }
    friend class WeakPtr<T>; // 方便weak_ptr与share_ptr设置引用计数和赋值

protected:
    void release()  // 释放原管理对象所有权,若引用计数为0,回收所管理对象的内存
    {
        cnt->s--;  // 引用计数减1
        cout << "release " << cnt->s << endl;
        if (cnt->s < 1)
        {
            delete _ptr;
            if (cnt->w < 1)
            {
                delete cnt;
                cnt = NULL;
            }
        }
    }

private:
    T *_ptr;  // 所管理对象的指针
    Counter *cnt;  // 每个share_ptr都有独立的的引用计数器,同一个管理对象所对应的所有share_ptr中的计数值一致
};

share_ptr的给出的函数接口为:构造,拷贝构造,赋值,解引用,通过release来在引用计数为0的时候删除_ptr和cnt的内存。

weak_ptr简单实现

template <class T>
class WeakPtr
{
public: //给出默认构造和拷贝构造,其中拷贝构造不能有从原始指针进行构造
	WeakPtr()  // 默认构造
	{
		_ptr = 0;
		cnt = new Count();
	}
	WeakPtr(SharePtr<T> &s) : _ptr(s._ptr), cnt(s.cnt)  // 通过share_str拷贝构造
	{
		cout << "w con s" << endl;
		cnt->w++;  // 为所管理对象的weak_ptr计数
	}
	WeakPtr(WeakPtr<T> &w) : _ptr(w._ptr), cnt(w.cnt)  // 通过weak_str拷贝构造
	{
		cnt->w++;  // 为所管理对象的weak_ptr计数
	}
	~WeakPtr()
	{
		release();
	}
	WeakPtr<T> &operator=(WeakPtr<T> &w)  // 通过weak_ptr赋值
	{
		if (this != &w)  // 防止自我赋值
		{
			release();  // 释放原管理对象
			cnt = w.cnt;
			cnt->w++;
			_ptr = w._ptr;
		}
		return *this;
	}
	WeakPtr<T> &operator=(SharePtr<T> &s)  // 通过share_ptr赋值
	{
		cout << "w = s" << endl;
		release();
		cnt = s.cnt;
		cnt->w++;
		_ptr = s._ptr;
		return *this;
	}
	SharePtr<T> lock()  // lock方法将weak_ptr转换为share_ptr
	{
		return SharePtr<T>(*this);  // 调用share_ptr的拷贝构造
	}
	bool expired()  // 判断所管理对象是否被释放
	{
		if (cnt)  // Count指针非空
		{
			if (cnt->s > 0)  // 引用计数不为0,返回false
			{
				cout << "empty" << cnt->s << endl;
				return false;
			}
		}
		return true;  // 其他返回true
	}
	friend class SharePtr<T>; //方便weak_ptr与share_ptr设置引用计数和赋值

protected:
	void release()
	{
		if (cnt)
		{
			cnt->w--;  // weak_ptr计数减1
			cout << "weakptr release" << cnt->w << endl;
			if (cnt->w < 1 && cnt->s < 1)  // weak_ptr与share_ptr计数均为0
			{
				//delete cnt;
				cnt = NULL;
			}
		}
	}

private:
	T *_ptr;
	Counter *cnt;
};

weak_ptr一般通过share_ptr来构造,通过expired函数检查原始指针是否为空,lock来转化为share_ptr。

  • 0
    点赞
  • 0
    评论
  • 3
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

©️2021 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值