C++智能指针weak_ptr

1.3 weak_ptr

  • share_ptr虽然已经很好用了,但是有一点share_ptr智能指针还是有内存泄露的情况,当两个对象相互
    使用一个shared_ptr成员变量指向对方,会造成循环引用,使引用计数失效,从而导致内存泄漏。
  • weak_ptr 是一种不控制对象生命周期的智能指针, 它指向一个 shared_ptr 管理的对象. 进行该对象的内
    存管理的是那个强引用的shared_ptr, weak_ptr只是提供了对管理对象的一个访问手段。
  • weak_ptr 设计的目的是为配合 shared_ptr 而引入的一种智能指针来协助 shared_ptr 工作, 它只可以从
    一个 shared_ptr 或另一个 weak_ptr 对象构造, 它的构造和析构不会引起引用记数的增加或减少。

1.3.1 weak_ptr基本用法

  1. 通过use_count()方法获取当前观察资源的引用计数,如下所示:
shared_ptr<int> sp(new int(10));
weak_ptr<int> wp(sp);
cout << wp.use_count() << endl; //结果讲输出1
  1. 通过expired()方法判断所观察资源是否已经释放,如下所示:
shared_ptr<int> sp(new int(10));
weak_ptr<int> wp(sp);
if(wp.expired())
	cout << "weak_ptr无效,资源已释放";
else
	cout << "weak_ptr有效";
  1. 通过lock()方法获取监视的shared_ptr,并且如果资源还在的情况会锁住资源(如果其他的智能指针要释放资源的话),且必须要先lock()主资源再用expired()判断资源释放已经释放,如下所示:
std::weak_ptr<int> gw;
void f()
{
	//锁住资源
	// 1. 资源还在
	// 2. 资源已经释放
	auto spt = gw.lock();
	if(gw.expired()) {
		cout << "gw无效,资源已释放";
	}
	else {
		cout << "gw有效, *spt = " << *spt << endl;
	}
}
int main()
{
	{
		auto sp = std::make_shared<int>(42);
		gw = sp;
		f();
	}
	f();
	return 0;
}

1.3.2 weak_ptr返回this指针

shared_ptr章节中提到不能直接将this指针返shared_ptr,需要通过派生std::enable_shared_from_this类,并通过其方法shared_from_this来返回指针,原因是std::enable_shared_from_this类中有一个weak_ptr,这个weak_ptr用来观察this智能指针,调用shared_from_this()方法是,会调用内部这个weak_ptr的lock()方法,将所观察的shared_ptr返回,再看前面的范例

#include <iostream>
#include <memory>
using namespace std;
class A: public std::enable_shared_from_this<A>
{
public:
	shared_ptr<A>GetSelf()
	{
		return shared_from_this(); //
	}
	~A()
	{
		cout << "Destructor A" << endl;
	}
};
int main()
{
	shared_ptr<A> sp1(new A);
	shared_ptr<A> sp2 = sp1->GetSelf(); // ok
	return 0;
}

1.3.3 weak_ptr解决循环引用问题

weak_ptr是一种用于解决shared_ptr相互引用时产生死锁问题的智能指针。如果有两个shared_ptr相互引用,那么这两个shared_ptr指针的引用计数永远不会下降为0,资源永远不会释放。weak_ptr是对对象的一种弱引用,它不会增加对象的use_count,weak_ptr和shared_ptr可以相互转化,shared_ptr可以直接赋值给weak_ptr,weak_ptr也可以通过调用lock函数来获得shared_ptr。

  • weak_ptr指针通常不单独使用,只能和 shared_ptr 类型指针搭配使用。将一个weak_ptr绑定到一个shared_ptr不会改变shared_ptr的引用计数。一旦最后一个指向对象的shared_ptr被销毁,对象就会被释放。即使有weak_ptr指向对象,对象也还是会被释放。
  • weak_ptr并没有重载operator->operator *操作符,因此不可直接通过weak_ptr使用对象,典型的用法是调用其lock函数来获得shared_ptr示例,进而访问原始对象。
#include <iostream>
#include <memory>
using namespace std;
class A;
class B;
class A {
public:
	std::weak_ptr<B> bptr; // 修改为weak_ptr
	~A() {
		cout << "A is deleted" << endl;
	}
};
class B {
public:
	std::shared_ptr<A> aptr;
	~B() {
		cout << "B is deleted" << endl;
	}
};
int main()
{
	{
		std::shared_ptr<A> ap(new A);
		std::shared_ptr<B> bp(new B);
		ap->bptr = bp;//由于bptr是weak_ptr类型,所以bp的引用计数不会+1,故bp.use_count() = 1
		bp->aptr = ap;//而ap的引用计数此时为ap.use_count() = 2
	}
	//bp出作用域的时候引用计数-1 为0 故而释放资源, 同时bp->aptr也会释放使得 ap的引用计数减1 为 1
	//ap本身释放资源使得计数减1 为0 最终释放资源
	
	cout<< "main leave" << endl;
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

coison_z

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值