,c++,smart-pointers"/>

首页 > 解决方案 > 为什么“weak.lock()”返回“nullptr”,定义为“auto weak=std::make_shared”(42);"?

问题描述

为什么在此代码片段中weak.lock()返回:nullptr

   std::weak_ptr<int> weakPtr1 = std::make_shared<int>(6);
   std::cout << weakPtr1.lock() << std::endl;

而它适用于以下一个:

   std::shared_ptr<int> sharedPtr = std::make_shared<int>(99);
   std::weak_ptr<int> weakPtr2 = sharedPtr;
   std::cout << weakPtr2.lock() << std::endl;

检查 cpp.sh/9gkys。

我想了又想,但我现在仍然很困惑。对于这个问题,我将不胜感激。

标签: c++smart-pointers

解决方案


智能指针为了正常工作,维护一个所谓的控制块,用作元数据存储,特别是使用计数器。也就是说,每个资源在内存中都有一个关联的控制块(例如由两个整数组成),智能指针可以参考这些控制块,以了解其中有多少仍在使用/观察资源。显然,每一个存在都会std::shared_ptr增加存储在控制块中的使用计数器,以便它的析构函数知道是否是时候在销毁时释放资源了。std::weak_ptr,反过来,只跟踪对象及其控制块。请注意,这是一个重要的细节:std::weak_ptr不会增加使用计数器。这是可取的,因为它的主要目的是打破一对相互观察的物体之间可能的循环。也就是说,如果两个对象将std::shared_ptrs 存储到另一个对象,那么这样一对对象也将无限地保持彼此的生命。

如何std::weak_ptr知道资源是否可以lock()编辑?只有当使用计数器大于零时,这才能成功。它从控制块中知道这一点(只要还有非零弱指针观察它,它本身就在内存中保持活动状态)。

在第一个示例中:

std::weak_ptr<int> weakPtr1 = std::make_shared<int>(6);

资源 ( int=6) 和它的控制块都被分配。使用计数器变为1,并且只要std::shared_ptr活着就一直存在。然后,astd::weak_ptr被初始化,得到一个指向控制块的指针。在这里,它不会增加使用计数器。但是,它会增加弱指针的计数器。此时,两个计数器都是1。然后,在分号处;,临时std::shared_ptr对象被销毁。它将使用计数器减少到0。这意味着不再有共享指针共享资源的所有权,从而允许释放该资源。但是,仍然有1弱指针观察控制块,这意味着控制块本身将保留在内存中,因此weakPtr1知道它无法lock()该资源不再存在(因为该资源不再存在)。

在第二个例子中:

std::shared_ptr<int> sharedPtr = std::make_shared<int>(99);
std::weak_ptr<int> weakPtr2 = sharedPtr;

资源int=99及其控制块都保持活动状态。因此weakPtr2,只要sharedPtr(或其任何副本)未被破坏,就可以被锁定。


推荐阅读