weak_ptr.lock()是唯一安全转为shared_ptr的方式,返回有效shared_ptr或空指针,必须判空后使用,否则可能访问已释放内存。

weak_ptr.lock() 是唯一安全的转换方式
直接用 shared_ptr 构造函数或强制转型(比如 static_cast)把 weak_ptr 转成 shared_ptr 会编译失败或引发未定义行为。唯一标准、线程安全、且带生命周期检查的方法就是调用 lock() —— 它返回一个 shared_ptr,如果原 weak_ptr 指向的对象还活着,就增加引用计数;否则返回空 shared_ptr。
必须检查 lock() 返回值是否为空
lock() 不抛异常,也不保证成功。常见错误是拿到返回值后直接解引用,结果触发 std::bad_weak_ptr 或访问已释放内存:
auto wp = std::weak_ptr<int>(sp); // sp 是 valid shared_ptr
auto sp2 = wp.lock(); // ✅ 正确调用
if (sp2) { // ✅ 必须判空
std::cout
<ul>
<li>即使刚从 <code>shared_ptr</code> 构造出 <code>weak_ptr</code>,也不能跳过判空——因为其他线程可能刚好在你调用 <code>lock()</code> 前释放了最后一个 <code>shared_ptr</code>
</li>
<li>
<code>if (wp.lock())</code> 是合法写法,但可读性差;建议拆成两步:先 <code>auto sp2 = wp.lock();</code>,再 <code>if (sp2)</code>
</li>
<li>不要用 <code>wp.expired()</code> 替代判空:它只是等价于 <code>!wp.lock()</code>,多一次原子操作,且仍需再调一次 <code>lock()</code> 才能用</li>
</ul>
<h3>lock() 的线程安全性与性能开销</h3>
<p><code>lock()</code> 内部对控制块做原子读,是线程安全的,多个线程并发调用不会导致数据竞争。但它有轻微性能成本:</p><div class="aritcle_card flexRow artxards">
<div class="artcardd flexRow">
<a class="aritcle_card_img" rel="nofollow" href="/xiazai/gongju/2823" title="C++14"><img
src="https://img.php.cn/upload/manual/001/431/639/6ac8b33c327c4749.png" alt="C++14" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a>
<div class="aritcle_card_info flexColumn">
<a rel="nofollow" href="/xiazai/gongju/2823" title="C++14" class="overflowclass">C++14</a>
<p class="overflowclass">C++14 对 C++11 的修正与增强版本,适合旧系统维护和较老工具链兼容。</p>
</div>
<a rel="nofollow" href="/xiazai/gongju/2823" title="C++14" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span>
</a>
</div>
</div>
<ul>
<li>每次调用都涉及原子操作和引用计数检查,高频调用(如循环内)应避免反复 <code>lock()</code>
</li>
<li>若逻辑上需要多次访问对象,应一次性 <code>lock()</code> 并持有返回的 <code>shared_ptr</code>,而不是每次访问都重新 <code>lock()</code>
</li>
<li>不推荐在锁保护区内调用 <code>lock()</code> 来“规避竞争”——<code>weak_ptr</code> 本就是为无锁场景设计的,加锁反而抵消其优势</li>
</ul>
<h3>典型误用:把 weak_ptr 当普通指针用</h3>
<p>有人试图用 <code>weak_ptr.get()</code> 或 <code>&*wp.lock()</code> 获取裸指针长期保存,这是危险的:</p>
<ul>
<li>
<code>weak_ptr.get()</code> 不存在——<code>weak_ptr</code> 没有 <code>get()</code> 成员函数</li>
<li>
<code>&*wp.lock()</code> 得到的裸指针只在当前 <code>shared_ptr</code> 生命周期内有效;一旦该 <code>shared_ptr</code> 离开作用域,指针立即悬空</li>
<li>若需缓存地址,必须同时持有 <code>shared_ptr</code>(即 <code>lock()</code> 结果),不能只存裸指针</li>
</ul>
<p>真正需要裸指针的场景极少,多数时候该重构为持有 <code>shared_ptr</code> 或改用观察者模式。</p></int>C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










