16.4 weak_ptr简介、weak_ptr常用操作与尺寸问题

一、weak_ptr简介

weak_ptr 辅助 shared_ptr 进行工作;
强指的就是 shared_ptr,弱指的就是 weak_ptr。
weak_ptr:也是个类模板,也是个智能指针,这个智能指针指向一个由 shared_ptr 管理的对象,但是 weak_ptr 这种指针不控制所指向对象的生命周期。
换句话来说,将 weak_ptr 绑定到 shared_ptr 上并不会改变 shared_ptr 的引用计数(更确切的说,weak_ptr 的构造和析构不会增加或减少所指向对象的引用计数)。
当 shared_ptr 需要释放所指定的时候照常释放,不管是否有 weak_ptr 指向该对象。
weak 这个意思 “弱” 能力弱(若共享/弱引用;共享其他的 shared_ptr 所指向的对象);控制不了所指向对象的生命周期。

这个弱引用( weak_ptr )的作用:大家可以理解成监视 shared_ptr (强引用)的生命周期用,是一种对 shared_ptr 能力的扩充。
weak_ptr 不是一种独立的智能指针,不能用来操作所指向的资源,所以它看起来像是一个shared_ptr 的助手。(旁观者)
weak_ptr 能够监视到它所指向的对象是否存在;

<1>weak_ptr创建
我们创建 weak_ptr 的时候,一般是用一个 shared_ptr 来初始化;

int main()
{
	auto pi = make_shared(100);  //shared_ptr
	weak_ptr piw(pi);  // piw弱共享pi,pi引用计数(强引用计数不会改变)不会改变,
							// 但是弱引用计数会改变(弱引用计数会从0变为1);
	return 0;
}

强引用计数才能决定对象的生存期,弱引用计数对对象生存期没有影响

int main()
{
	auto pi = make_shared(100);  //shared_ptr
	weak_ptr piw;
	piw = pi;  //pi是一个shared_ptr,赋值给一个weak_ptr,两者指向同一个内存对象;
	weak_ptr piw2;
	piw2 = piw;  //把weak_ptr赋给另外一个weak_ptr,现在pi是一个强引用,piw和piw2是两个弱引用;
	weak_ptr piw2(piw);
	return 0;
}

lock():功能就是检查weak_ptr所指向的对象是否存在,如果存在,那么这个lock他就能够返回一个指向该对象的shared_ptr
(指向对象的强引用计数加一)
如果所指向的对象不存在,lock返回一个空的shared_ptr

int main()
{
	auto pi = make_shared(100);  //shared_ptr
	weak_ptr piw;
	piw = pi;  //pi是一个shared_ptr,赋值给一个weak_ptr,两者指向同一个内存对象;
	weak_ptr piw2;
	piw2 = piw;  //把weak_ptr赋给另外一个weak_ptr,现在pi是一个强引用,piw和piw2是两个弱引用;
	weak_ptr piw2(piw);
	pi.reset();   // 因为pi是唯一指向该对象的强引用智能指针,所以reset()会释放pi所指向的对象,同时将pi置空
	auto pi2 = piw.lock();  //pi2是一个shared_ptr
	if (pi2 != nullptr)  //也可以写成if(pi2)
	{
		//所指向的对象存在
		*pi2 = 12;
	}
	else
	{
		cout << "很遗憾,lock()失败" << endl;
	}

	return 0;
}

总结上面这段代码:weak_ptr 能够判断所指向的对象是否存在,这种能力。

二:weak_ptr常用操作

<1>use_count
获取与该弱指针所共享对象的其他 shared_ptr 的数量,或者说获得当前所观测资源的强引用计数;

int main()
{
	auto pi = make_shared(100);
	auto pi2(pi);  //是一个shared_ptr;
	weak_ptr piw(pi);
	auto piw2(piw);
	int isc = piw.use_count();
	cout << isc << endl;
	return 0;
}

<2>expired()
是否过期的意思,弱指针的 use_count() 返回0表示该弱指针所指向的对象已经不存在了,则返回true,否则返回false。
换句话说,这个函数用来判断所观测的资源是否被释放

int main()
{
	auto pi = make_shared(100);
	auto pi2(pi);  //是一个shared_ptr;
	weak_ptr piw(pi);
	auto piw2(piw);
	pi.reset();
	pi2.reset();
	if (piw.expired())
	{
		cout << "对象已经过期" << endl;
	}
	return 0;
}

<3>reset()
将该弱指针置为空,不会影响指向该对象的强引用数量,但指向该对象的弱引用数量会减少1。
piw.reset();

<4>lock()

int main()
{
	auto pi = make_shared(100);
	auto pi2(pi);  //是一个shared_ptr;
	weak_ptr piw(pi);
	auto piw2(piw);
	pi.reset();
	pi2.reset();
	weak_ptr ptw;
	{
		auto p1 = make_shared(100);
		ptw = p1;  //可以用shared_ptr给weak_ptr赋值
	}
	//ptw就会过期;

	if (!ptw.expired())
	{
		auto p2 = ptw.lock();  //返回一个shared_ptr, 并且此时强引用计数为2;
		if (p2 != nullptr)
		{
			//做一些操作
			int test;
			test = 1;
			//离开这个范围,强引用计数,会恢复为1
		}
	}
	else
	{
		//已经过期
		int test;
		test = 1;
	}

	return 0;
}

走到这里,则强引用计数变回了1;

三:尺寸问题

weak_ptr pw;
weak_ptr和shared_ptr一样大,裸指针的2倍
int* p;
int ilen1 = sizeof§; //4个字节,是个裸指针
int ilen2 = sizeof(pw); //8个字节,两个裸指针

auto pi = make_shared(100); //后续还会继续讲解shared_ptr
weak_ptr piw(pi);

第一个裸指针指向的是这个智能指针所指向的对象;
第二个裸指针指向一个很大的数据结构(控制块),这个控制块里有:
1.所指对象的强引用计数
2.所指对象的弱引用计数
3.其他数据,比如自定义删除器的指针等等

总结: 基本具备能够读懂实战代码的能力。大家缺乏实战。

你可能感兴趣的:(c++学习,c++)