c++标准库(笔记):智能指针(2) -- weak_ptr

shared_ptr主要是为了避免操心指针指向的资源,保证在最后一个对象结束生命的时候其相应资源也被释放,但有些情形并不期望这样或无法运作:
1、环式指向:如果两对象使用shared_ptr互相指向对方,而一旦不存在外部引用指向他们时,这种情况下shared_ptr不会释放数据,因为每个对象的use_count()仍是1;

#include <iostream>
#include <string>
#include <utility>
#include <memory>

using std::cout;
using std::cin;
using std::endl;

class StructB;
class StructA
{
public:
	StructA() : m_pb(nullptr)
	{
		cout << "Contruct A" << endl;
	}
	~StructA()
	{
		cout << "Delete A" << endl;
	}
	void setStructB(std::shared_ptr<StructB> p)
	{
		m_pb = p;
	}
private:
	std::shared_ptr<StructB> m_pb;
};

class StructB
{
public:
	StructB():m_pa(nullptr)
	{
		cout << "Contruct B" << endl;
	}
	~StructB()
	{
		cout << "Delete B" << endl;
	} 
	void setStructA(std::shared_ptr<StructA> p)
	{
		m_pa = p;
	}
private:
	std::shared_ptr<StructA> m_pa;
};

int main()
{
	std::shared_ptr<StructA> a;
	std::shared_ptr<StructB> b;
	a.reset(new StructA);
	b.reset(new StructB);
	a->setStructB(b);
	b->setStructA(a);
	return 0;
}

最终程序输出:

2、引用的寿命比所指对象寿命更长:此时shared_ptr绝不释放对象,而寻常的指针可能不会注意到他们所指向的对象已经不再有效,导致“访问已被释放的数据”的风险。

因此标准库提供了weak_ptr,允许“共享但不拥有”某对象。
一旦最后一个对象释放掉以后,所有的weak pointer都将为空,因此,除了默认和复制构造函数之外,weak_ptr只提供接受一个shared_ptr的构造函数。
注:无法通过*和->访问weak_ptr指向的对象,而是必须建立另一个shared pointer。这样做基于以下两个理由:
1、在weak pointer之外建立一个shared pointer可检查是否仍存在一个响应对象。如果不存在,会抛出异常或建立一个空的shared_pointer
2、当指向的对象正被处理时,shared pointer无法被释放。基于以上:weak_ptr只提供少量操作:创建、复制、赋值以及转换成一个shared_ptr,或检查自己是否指向对象

使用weak pointer时,我们需要改变指向对象的访问方式:
p->mother->kids[0]->name;    //error
p->mother->kids[0].lock()->name;//ok
调用lock()会导致产生一个shared_ptr,这样的话,就有可能会产生一个空的shared_ptr,如果对象的最后拥有者已经被释放了的话。这种时候可以通过以下选择判断weak_ptr背后的对象是否还存活着:
1、expired():会在wea_ptr不再共享对象时返回true
2、使用shared_ptr构造函数将weak_ptr转换成一个shared_ptr,如果对象不存在,会抛出一个异常bad_weak_ptr
3、调用use_count():这通常只是为了调试使用,c++标准库明确指出“use_count()并不总是很有效率”

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值