← 模式
弱引用
12345678910111213141516171819202122232425262728293031323334 | #include <memory> class bar; class foo { public: foo(const std::shared_ptr<bar>& b) : forward_reference{b} { } private: std::shared_ptr<bar> forward_reference; }; class bar { public: void set_back_reference(const std::weak_ptr<foo>& f) { this->back_reference = f; } void do_something() { std::shared_ptr<foo> shared_back_reference = this->back_reference.lock(); if (shared_back_reference) { // 使用 *shared_back_reference } } private: std::weak_ptr<foo> back_reference; }; |
此模式采用 CC0 公共领域贡献 许可。
需要 c++11 或更新版本。
意图
维持一个对共享动态分配对象的非持有引用,以打破循环依赖。
描述
std::weak_ptr
类型表示一个对共享所有权(std::shared_ptr
)的动态分配对象的非持有引用。由于弱引用不会增加其所指向的被管理对象的引用计数,因此当所有 std::shared_ptr
放弃所有权时,该对象随时可能被销毁。然而,std::weak_ptr
可以转换为 std::shared_ptr
,以提供临时所有权并安全地访问对象。
在示例代码中,我们有两个类:第 5–14 行的 foo
和第 16–30 行的 bar
。一个 foo
对象拥有一个 bar
对象的部分所有权(第 13 行),而 bar
需要某种形式的反向引用,指回拥有它的 foo
。如果这个反向引用是 std::shared_ptr<foo>
,就会引入循环依赖,导致两个对象都无法被销毁。如果它是一个普通的引用类型(foo&
),则在使用它时可能引用一个已被删除的对象,因为 foo
的生命周期与 bar
是独立的。
解决方案是使用 std::weak_ptr<foo>
,如第 33 行所示。当 bar
需要使用 foo
时,它通过在 std::weak_ptr
上调用 lock
来获取临时的共享所有权(第 26 行),以此检查 foo
是否仍然存在。如果返回的 std::shared_ptr
不为空,bar
就可以安全地使用它来访问 foo
对象(第 27–29 行)。