智能指针第三篇——weak_ptr

目录

1.模拟实现加了weak_ptr后的shared_ptr:

1.1代码模拟简单实现:

1.2内存分布如图:

2.拷贝构造和赋值语句

3.解决shared_ptr的相互引用:


前边说过可以通过使用weak_ptr来解决shared_ptr的相互引用问题。本篇我们会从weak_ptr的构成和内纯分布来深入了解如何解决的。

weak_ptr一般都会和shared_ptr一起使用。weak_ptr的结构只有一个变量_Rep,较为简单,所以我们来看两者结合的shared_ptr。

1.模拟实现加了weak_ptr后的shared_ptr:

1.1代码模拟简单实现:

class Object
{
private:
	int value;
public:
	Object(int x = 0) :value(x) {};
	~Object() {};
	}
};

template<class _Ty>
class RefCnt
{
public:
	_Ty  *  _Ptr
	std::atomic_int _Uses;
	std::atomic_int _Weaks;

public:
	RefCnt(_Ty* p ) :mptr(p), _Uses(1),_Weaks(1){}
	~RefCnt() {}
	void _Incref() { _Uses += 1; }
	void _Incwref() { _Weaks += 1; }
};


template<class _Ty, class _Dx = MyDeletor<_Ty> >
class my_shared_ptr // thread;
{
private:
	_Ty*          _Ptr;
	RefCnt<_Ty>*  _Rep;
	_Dx mDeletor;
public:
	my_shared_ptr(_Ty* p = nullptr) :_Ptr(nullptr),_Rep(nullptr)
	{
		if (p != nullptr)
		{
			_Ptr = p;
			_Rep = new RefCnt(p);
		}
	}
    ~my_shared_ptr()
	{
		if (this->_Ptr != nullptr && --this->Rep->_Uses == 0)
		{
			mDeletor(_Ptr);
			if (-- this->_Rep->_Weaks == 0)
			{
				delete _Rep;
			}
		}
		_Ptr = nullptr;
		_Rep = nullptr;
	}
class my_weak_ptr 
{ 
private:
	RefCnt<_Ty>* _Rep;
public:
	my_weak_ptr()  {}

	my_weak_ptr(const my_weak_ptr& _Other) 
	{
		_Rep = _Other._Rep;
		if (_Rep != nullptr)
		{
			_Rep->_Incwref();
		}
	}
}

1.2内存分布如图:

int main()
{
    my_shared_ptr<Object>op1(new Object(10));
    return 0;
}

 

 此时的内存分布如图,op1和RefCnt都指向Object对象,此时的删除是关键。

删除的设置也很巧妙:

 ~my_shared_ptr()
	{
		if (this->_Ptr != nullptr && --this->Rep->_Uses == 0)
		{
			mDeletor(_Ptr);
			if (-- this->_Rep->_Weaks == 0)
			{
				delete _Rep;
			}
		}
		_Ptr = nullptr;
		_Rep = nullptr;
	}

在上边RefCnt结构中存有_Uses和_Weaks。当_Uses=0时,析构op1,;当_Weaks=0时,析构RefCnt结构。

2.拷贝构造和赋值语句

weak_ptr和shared_ptr的拷贝构造和赋值语句原理相同。只增加_Uses的值,但在赋值语句时,判断this指针所指对象时,要考虑_weaks的值,当Weaks的值为1,就会析构RefCnt结构。简单来说,就是强引用销毁时,_Uses和weaks都要-1,弱引用销毁时,只有_Weaks-1.

要想改变_Weaks的值,只能通过定义weak_ptr指针管理的对象,如weak_ptr<object>op2(new (Object(10))).

my_shared_ptr(const my_shared_ptr& _Y) :_Ptr(_Y._Ptr),_Rep(_Y._Rep)
	{
		if (_Ptr != nullptr)
		{
			_Rep->_Incref();
		}
	}
my_shared_ptr& operator=(const my_shared_ptr& _Y) // 
	{
		if (this == &_Y || this->_Ptr == _Y._Ptr) return *this;
		if (_Ptr != NULL && --_Rep->_Uses == 0)
		{
			mDeletor(_Ptr);
			if (--_Rep->_Weaks == 0)
			{
				delete _Rep;
			}
		}
		_Ptr = _Y._Ptr;
		_Rep = _Y._Rep
		if (_Rep != nullptr)
		{
			_Rep->_Uses += 1;
		}
		return *this;
	}

3.解决shared_ptr的相互引用:

weak_ptr的解决方法也很简单,把引用的shared_ptr换成weak_ptr即可。

class Child;
class Parent
{
public:
	weak_ptr<Child>child;
	Parent() { cout << "Create Parent" << endl; }
	~Parent() { cout << "Destory Parent" << endl; }
	void hi() { cout << "hello" << endl; }
};
class Child
{
public:
	weak_ptr<Parent>parent;
	Child() { cout << "Create Child" << endl; }
	~Child() { cout << "Destory Child" << endl; }

};
int main()
{
	shared_ptr<Parent>p = make_shared<Parent>();
	shared_ptr<Child>c = make_shared<Child>();
	p->child = c;
	c->parent = p;
	p->hi();
	return 0;
}

所以内存分布如图:

 这时只需要记着强引用销毁时,_Uses和weaks都要-1,弱引用销毁时,只有_Weaks-1.这边的释放过程特别重要,应反复琢磨。

运行结果:

 解决了shared_ptr互相引用不能释放的问题。

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值