为什么"weak.lock()"返回"nullptr" "auto weak=std::make_shared<int>(42);"的定义?

Why does "weak.lock()" return "nullptr" with the definition of "auto weak=std::make_shared<int>(42);"?

本文关键字:weak int lt gt 定义 lock shared auto nullptr 返回 std      更新时间:2023-10-16

为什么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。

我想了又想,但现在还是迷茫了。如果能在这个问题上得到一些帮助,我将不胜感激。

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

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

在第一个示例中:

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

资源(int=6(和它的控制块都被分配。使用计数器变得1,并且只要std::shared_ptr还活着,它就会保持这种状态。然后,初始化std::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及其控制块都保持活动状态。因此,只要sharedPtr(或其任何副本(不被销毁,就可以锁定weakPtr2

您的示例使用副本初始化。因此,建立在正确基础上的shared_ptr只存在到表达式的评估,然后被破坏:

  1. 在第一个例子中,这意味着不再有对shared_ptr的引用(我们不计算弱的(,因此lock返回 null。
  2. 在第二个中,您将结果绑定到局部变量,将生命周期延长到当前块 - 因此仍然有一个引用,并且没有空结果。