欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

C++智能指针weak_ptr详解

程序员文章站 2022-06-02 14:10:11
...

一、背景

weak_ptr这个指针是在C++11的时候引入的标准库,它的出现完全是为了弥补shared_ptr天生有缺陷的问题,其实相比于上一代的智能指针auto_ptr来说,shared_ptr可以说近乎完美,但由于是通过引用计数实现的它,虽然解决了指针独占的问题,但也引来了引用成环的问题,这种问题靠它自己是没办法解决的,所以在C++11的时候将shared_ptrweak_ptr一起引入了标准库,用来解决循环引用的问题。

C++智能指针weak_ptr详解

二、使用方法

std::weak_ptr 是一种智能指针,它对被 std::shared_ptr 管理的对象存在非拥有性(“弱”)引用。在访问所引用的对象前必须先转换为 std::shared_ptr

std::weak_ptr 用来表达临时所有权的概念:当某个对象只有存在时才需要被访问,而且随时可能被他人删除时,可以使用 std::weak_ptr 来跟踪该对象。需要获得临时所有权时,则将其转换为 std::shared_ptr,此时如果原来的 std::shared_ptr 被销毁,则该对象的生命期将被延长至这个临时的 std::shared_ptr 同样被销毁为止。

C++智能指针weak_ptr详解

三、实例

1.循环引用的例子

class BB;
class AA
{
public:
	AA() { cout << "AA::AA() called" << endl; }
	~AA() { cout << "AA::~AA() called" << endl; }
	shared_ptr<BB> m_bb_ptr;  //!
};

class BB
{
public:
	BB() { cout << "BB::BB() called" << endl; }
	~BB() { cout << "BB::~BB() called" << endl; }
	shared_ptr<AA> m_aa_ptr; //!
};
int main()
{

	shared_ptr<AA> ptr_a(new AA);
	shared_ptr<BB> ptr_b(new BB);
	cout << "ptr_a use_count: " << ptr_a.use_count() << endl;
	cout << "ptr_b use_count: " << ptr_b.use_count() << endl;
	//下面两句导致了AA与BB的循环引用,结果就是AA和BB对象都不会析构
	ptr_a->m_bb_ptr = ptr_b;
	ptr_b->m_aa_ptr = ptr_a;
	cout << "ptr_a use_count: " << ptr_a.use_count() << endl;
	cout << "ptr_b use_count: " << ptr_b.use_count() << endl;
        return 0;
}
	

结果

C++智能指针weak_ptr详解

可以看到由于AA和BB内部的shared_ptr各自保存了对方的一次引用,所以导致了ptr_a和ptr_b销毁的时候都认为内部保存的指针计数没有变成0,所以AA和BB的析构函数不会被调用。解决方法就是把一个shared_ptr替换成weak_ptr。

class BB;
class AA
{
public:
	AA() { cout << "AA::AA() called" << endl; }
	~AA() { cout << "AA::~AA() called" << endl; }
	weak_ptr<BB> m_bb_ptr;  //!
};

class BB
{
public:
	BB() { cout << "BB::BB() called" << endl; }
	~BB() { cout << "BB::~BB() called" << endl; }
	shared_ptr<AA> m_aa_ptr; //!
};

运行结果: 

C++智能指针weak_ptr详解

2.通过锁来保证指针的有效性的例子


std::weak_ptr<int> gw;

void f()
{
	if (auto spt = gw.lock()) { // 使用之前必须复制到 shared_ptr
		std::cout << *spt << "\n";
	}
	else {
		std::cout << "gw is expired\n";
	}
}
int main()
{
	{
		auto sp = std::make_shared<int>(42);
		gw = sp;

		f();
	}

	f();
        return 0;
}

C++智能指针weak_ptr详解

四、总结

  1. weak_ptr虽然是一个模板类,但是不能用来直接定义指向原始指针的对象。
  2. weak_ptr接受shared_ptr类型的变量赋值,但是反过来是行不通的,需要使用lock函数。
  3. weak_ptr设计之初就是为了服务于shared_ptr的,所以不增加引用计数就是它的核心功能。
  4. 由于不知道什么之后weak_ptr所指向的对象就会被析构掉,所以使用之前请先使用expired函数检测一下。

 

参考:

https://blog.csdn.net/albertsh/article/details/82286999

https://blog.csdn.net/c_base_jin/article/details/79440999?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.compare&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.compare

https://blog.csdn.net/Xiao_CangTian/article/details/89764858?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-9.compare&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-9.compare#1.%20%E5%87%A0%E7%A7%8D%E6%99%BA%E8%83%BD%E6%8C%87%E9%92%88

相关标签: C++