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<int> w;</int>)→w.expired()返回true - 指向已释放对象的
std::weak_ptr→expired()也返回true - 两者行为一致,但原因不同:前者无控制块,后者控制块中 shared_count == 0
典型使用场景:避免 lock() 失败后的空解引用
多数时候你真正需要的是「对象还活着,且我能安全访问」,这时应优先用 lock() 并检查返回值,而不是先 expired() 再 lock() —— 因为两次调用之间存在竞态窗口(尤其在多线程中)。
但如果只是做快速过滤(比如清理缓存容器中已失效的项),expired() 就很合适:
立即学习“C++免费学习笔记(深入)”;
std::vector<std::weak_ptr<Data>> cache;
// 清理已销毁对象的弱引用
cache.erase(
std::remove_if(cache.begin(), cache.end(),
[](const std::weak_ptr<Data>& 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。











