c++中如何使用std::weak_ptr的expired方法_c++智能指针状态检查【实例】

expired() 仅检测对象是否销毁,不能判断 weak_ptr 是否为空;空 weak_ptr 和指向已销毁对象的 weak_ptr 均返回 true,但原因不同:前者无控制块,后者共享引用计数为零。

std::weak_ptr::expired() 用来快速判断所指对象是否已销毁

它比 lock() 更轻量,只检查引用计数是否为 0,不尝试升级为 std::shared_ptr。适合做前置状态校验,避免无谓的锁升级开销。

为什么不能用 expired() 判断“是否为空”

expired() 只反映所管理对象是否还存在,和 weak_ptr 本身是否为空(即是否调用过默认构造或 reset)无关。一个刚构造的空 std::weak_ptr 调用 expired() 会返回 true,但这不是因为对象被销毁,而是它根本没关联任何控制块。

  • std::weak_ptr(如 std::weak_ptr w;)→ w.expired() 返回 true
  • 指向已释放对象的 std::weak_ptrexpired() 也返回 true
  • 两者行为一致,但原因不同:前者无控制块,后者控制块中 shared_count == 0

典型使用场景:避免 lock() 失败后的空解引用

多数时候你真正需要的是「对象还活着,且我能安全访问」,这时应优先用 lock() 并检查返回值,而不是先 expired()lock() —— 因为两次调用之间存在竞态窗口(尤其在多线程中)。

但如果只是做快速过滤(比如清理缓存容器中已失效的项),expired() 就很合适:

std::vector> cache;
// 清理已销毁对象的弱引用
cache.erase(
    std::remove_if(cache.begin(), cache.end(),
        [](const std::weak_ptr& wp) { return wp.expired(); }),
    cache.end()
);

和 lock() + 检查 operator bool 的性能与语义差异

expired() 是原子读,通常编译为单条内存加载指令;lock() 需要原子递增 shared_count,失败时还要回退,开销明显更高。

  • 仅需知道“是否已死” → 用 expired()
  • 需要访问对象内容 → 必须用 auto sp = wp.lock(); if (sp) { ... }
  • 不要写 if (!wp.expired()) { auto sp = wp.lock(); ... }:多一次原子操作,且仍可能在 lock 前被销毁

多线程下 expired() 返回 false 只保证「此刻对象还活着」,不保证下一毫秒它不会被最后一个 shared_ptr 释放。真正安全的访问必须依赖 lock() 成功返回的非空 shared_ptr