You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何从已过期的std::weak_ptr创建共享其control block的std::shared_ptr?

如何从已过期的std::weak_ptr创建共享其control block的std::shared_ptr?

首先我们拆解你测试现象背后的C++标准规则,再回到你的核心需求来解答。

先解释你观察到的测试结果

你的输出完全符合C++标准对智能指针控制块的定义,我们逐个拆解:

  1. expired.lock()返回的shared_ptr和原weak_ptr控制块不同
    weak_ptr指向的对象已经销毁(expired() == true),标准规定lock()会返回一个无控制块的空shared_ptr——和默认构造的空智能指针完全等价。这是因为原控制块的use_count已经为0,对象不存在的情况下,持有该控制块的shared_ptr没有实际内存管理意义,标准库设计时就选择返回无控制块的空指针。

  2. 两种“空智能指针”的本质区别
    C++里的空智能指针分为两种状态:

    • 无控制块的空:比如默认构造的shared_ptr/weak_ptr、用nullptr直接构造的shared_ptrlock()返回的空shared_ptr。这类指针不关联任何控制块,所以owner_before会判定它们彼此等价。
    • 有控制块但指针为空:比如用static_cast<int*>(nullptr)构造的shared_ptr。这类指针会创建一个独立的控制块(虽然管理的原始指针是nullptr),所以和无控制块的空智能指针的owner_before结果不同。

这直接解释了你测试里的所有输出:

  • locked_expired是无控制块的空,所以和持有原控制块的expired不等价,但和无控制块的empty等价;
  • null_emptynullptr构造)是无控制块的空,和empty等价;
  • null_nonemptystatic_cast<int*>(nullptr)构造)有独立控制块,和empty不等价。

核心需求:能不能创建和过期weak_ptr共享控制块的shared_ptr?

很遗憾,C++标准库没有提供直接实现这个需求的方法

原因有两点:

  • 从设计逻辑看:过期weak_ptr的控制块use_count已经为0,对象已销毁,持有该控制块的空shared_ptr既不能管理任何对象,也不会改变控制块的生命周期(控制块会等到所有weak_ptr销毁后才回收),完全没有实际价值;
  • 从接口限制看:控制块是标准库的内部实现细节,不同编译器的控制块结构可能不同,标准也没有暴露任何直接操作控制块的公开接口,你无法手动构造出关联该控制块的shared_ptr。

替代方案:如果需要追踪控制块归属

如果你的场景是需要追踪智能指针的“来源控制块”(而非对象是否存在),可以通过自定义包装类实现:
在创建原始shared_ptr时,给每个控制块绑定一个唯一标识(比如UUID),然后用自定义的weak_ptr包装类保存这个标识。这样即使对象过期,你也可以通过标识判断两个智能指针是否来自同一个原始控制块。


内容来源于stack exchange

火山引擎 最新活动