c++ - 为什么“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。
我想了又想,但我现在仍然很困惑。对于这个问题,我将不胜感激。
解决方案
智能指针为了正常工作,维护一个所谓的控制块,用作元数据存储,特别是使用计数器。也就是说,每个资源在内存中都有一个关联的控制块(例如由两个整数组成),智能指针可以参考这些控制块,以了解其中有多少仍在使用/观察资源。显然,每一个存在都会std::shared_ptr
增加存储在控制块中的使用计数器,以便它的析构函数知道是否是时候在销毁时释放资源了。std::weak_ptr
,反过来,只跟踪对象及其控制块。请注意,这是一个重要的细节:std::weak_ptr
不会增加使用计数器。这是可取的,因为它的主要目的是打破一对相互观察的物体之间可能的循环。也就是说,如果两个对象将std::shared_ptr
s 存储到另一个对象,那么这样一对对象也将无限地保持彼此的生命。
如何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
(或其任何副本)未被破坏,就可以被锁定。
推荐阅读
- java - 使用字典 Java 进行高效的字符串搜索
- android-studio - 如何从 Flutter App 中删除 Kotlin 支持?
- java - 无法使用多个spring事件监听器实例
- java - 从列表java中抓取数据
- tfs - Azure DevOps/TFS 缓存扩展数据在哪里
- google-maps - 如何在 Cordova 应用程序中保护 Google Maps JS api 密钥?
- c# - 如何在项目准备好后立即解析 IAsyncEnumerables 列表
- electron - 使用 OpenVidu 和电子进行视频录制
- javascript - TypeError:props.tracks.map 不是函数
- vue.js - 当我关闭 bootstrap4 模态控制台显示'[Violation] Forced reflow while execution JavaScript take xxms'