【问题标题】:std::weak_ptr::lock and object destructionstd::weak_ptr::lock 和对象销毁
【发布时间】:2021-07-06 20:24:11
【问题描述】:

我知道在多线程环境中检查对象是否已被std::shared_ptr<T>::use_count() == 0 完全删除是不安全的,因为对象的析构函数可能仍未完成。

但是改用std::weak_ptr::lock() 怎么样?

if (weak_ptr.lock() == nullptr) {
    // The object's destructor is guaranteed to be completed?
}

【问题讨论】:

  • 不,lock() 还会告诉您该对象是否仍然可以安全使用(尚未做出销毁该对象的决定)。你甚至都不知道析构函数已经开始运行,更不用说完成了。
  • use_count() == 0 不起作用的原因是因为如果共享指针不管理对象,它只是 0。如果你有一个指向某物的共享指针,那么use_count 将至少为 1。一旦你重置指针,你就不知道它曾经指向的对象的状态。
  • 我不确定是否有任何方法可以确定对象的析构函数已完成,除了可能监视管理该对象存储的分配器。如果存储变得可用,则对象的生命周期已经结束。但是,即使您将某种事件信号直接放在析构函数的末尾,您也无法知道调用函数在发出事件信号后是否真的返回了。首先,这似乎是一个奇怪的要求。你能分享一下你为什么需要这个吗?
  • 标准相当神秘:“[util.smartptr.shared]/5use_count() 的更改不反映可能引入数据竞争的修改。”我不知道怎么读。但是,我相信~shared_ptr 的任何合理实现都会首先将use_count 减少为零,然后销毁底层对象,这样就不可能获得一个指向中途对象的即将悬空的指针通过破坏。 weak_ptr.lock() == nullptr 告诉你最后一个 shared_ptr 实例已经开始销毁,但不知道它持有的对象是否这样做。
  • 如果weak_ptr.lock() 返回nullptr,这意味着对象的生命周期已经不可撤销地过期,不再有。析构函数可能已经完成,也可能没有完成,但是由于对象的指针现在是不可恢复的(除非之前存储在智能指针之外),所以了解析构函数的唯一方法是析构函数是否有其他副作用。请注意,“销毁”不一定与“我的程序现在使用更少的内存”相同,因为链接到它的底层分配器可能会保留已释放的内存,以防以后需要更多内存,以最大限度地减少昂贵的系统调用。跨度>

标签: c++ multithreading shared-ptr weak-ptr


【解决方案1】:

以下应该都是等价的:

weak_ptr.use_count() == 0
weak_ptr.lock() == nullptr
weak_ptr.expired()

他们认为最后一个管理shared_ptr 已经开始毁灭。它们并不意味着托管对象尚未开始销毁,也不表示已完成销毁。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-03-12
    • 1970-01-01
    • 1970-01-01
    • 2021-07-28
    • 2023-03-24
    • 1970-01-01
    • 2014-12-17
    • 1970-01-01
    相关资源
    最近更新 更多