跳转到内容
主菜单
主菜单
移至侧栏
隐藏
导航
首页
最近更改
随机页面
MediaWiki帮助
代码酷
搜索
搜索
中文(中国大陆)
外观
创建账号
登录
个人工具
创建账号
登录
未登录编辑者的页面
了解详情
贡献
讨论
编辑“︁
C++ weak ptr
”︁
页面
讨论
大陆简体
阅读
编辑
编辑源代码
查看历史
工具
工具
移至侧栏
隐藏
操作
阅读
编辑
编辑源代码
查看历史
常规
链入页面
相关更改
特殊页面
页面信息
外观
移至侧栏
隐藏
您的更改会在有权核准的用户核准后向读者展示。
警告:
您没有登录。如果您进行任何编辑,您的IP地址会公开展示。如果您
登录
或
创建账号
,您的编辑会以您的用户名署名,此外还有其他益处。
反垃圾检查。
不要
加入这个!
{{DISPLAYTITLE:C++ weak_ptr}} '''C++ weak_ptr''' 是 C++ 标准库中提供的一种智能指针,用于解决共享所有权模型中的循环引用问题。它是 `std::shared_ptr` 的伴随指针,本身不增加引用计数,但可以安全地观察 `shared_ptr` 管理的对象是否存在。 == 介绍 == `std::weak_ptr` 是一种不控制对象生命周期的智能指针,它指向一个由 `std::shared_ptr` 管理的对象。与 `shared_ptr` 不同,`weak_ptr` 不会增加对象的引用计数,因此不会阻止对象的销毁。其主要用途包括: * 打破 `shared_ptr` 之间的循环引用 * 临时访问 `shared_ptr` 管理的对象(需通过 `lock()` 方法) * 观察资源是否存在而不影响其生命周期 == 基本用法 == === 创建 weak_ptr === `weak_ptr` 通常从 `shared_ptr` 构造或赋值: <syntaxhighlight lang="cpp"> #include <memory> #include <iostream> int main() { std::shared_ptr<int> shared = std::make_shared<int>(42); std::weak_ptr<int> weak(shared); // 从 shared_ptr 构造 // 检查对象是否还存在 if (auto temp = weak.lock()) { std::cout << "Value: " << *temp << "\n"; // 输出: Value: 42 } else { std::cout << "Object already destroyed\n"; } shared.reset(); // 释放所有权 if (weak.expired()) { std::cout << "Object has been destroyed\n"; // 输出: Object has been destroyed } } </syntaxhighlight> === 主要成员函数 === * `lock()`: 返回一个 `shared_ptr`,若原对象存在则共享所有权,否则返回空 * `expired()`: 检查被观察对象是否已被释放 * `use_count()`: 返回共享该对象的 `shared_ptr` 数量 == 解决循环引用 == 循环引用是 `shared_ptr` 的常见问题,会导致内存泄漏。以下示例展示如何使用 `weak_ptr` 解决此问题: === 问题示例 === <syntaxhighlight lang="cpp"> struct Node { std::shared_ptr<Node> next; ~Node() { std::cout << "Node destroyed\n"; } }; int main() { auto node1 = std::make_shared<Node>(); auto node2 = std::make_shared<Node>(); node1->next = node2; // node1 引用 node2 node2->next = node1; // node2 引用 node1 → 循环引用 // 退出作用域时,引用计数不为0,内存泄漏! } </syntaxhighlight> === 解决方案 === 将其中一个指针改为 `weak_ptr`: <syntaxhighlight lang="cpp"> struct Node { std::weak_ptr<Node> next; // 改为 weak_ptr ~Node() { std::cout << "Node destroyed\n"; } }; int main() { auto node1 = std::make_shared<Node>(); auto node2 = std::make_shared<Node>(); node1->next = node2; node2->next = node1; // 不会增加引用计数 // 退出作用域时对象会被正确销毁 // 输出: Node destroyed\nNode destroyed } </syntaxhighlight> == 实际应用场景 == === 缓存系统 === `weak_ptr` 适合实现对象缓存,当外部不再需要缓存项时允许自动清理: <syntaxhighlight lang="cpp"> class Cache { std::unordered_map<int, std::weak_ptr<Resource>> cache; public: std::shared_ptr<Resource> get(int id) { if (auto it = cache.find(id); it != cache.end()) { if (auto res = it->second.lock()) { return res; // 缓存命中 } } // 缓存未命中,创建新资源 auto res = std::make_shared<Resource>(id); cache[id] = res; return res; } }; </syntaxhighlight> === 观察者模式 === 观察者可以使用 `weak_ptr` 观察主体,避免影响主体生命周期: <syntaxhighlight lang="cpp"> class Subject { std::vector<std::weak_ptr<Observer>> observers; public: void notify() { for (auto& weak_obs : observers) { if (auto obs = weak_obs.lock()) { obs->update(); } } } }; </syntaxhighlight> == 性能与安全考虑 == * **性能**: `lock()` 操作包含原子操作,比裸指针访问稍慢 * **线程安全**: 与 `shared_ptr` 类似,`weak_ptr` 的基本操作是线程安全的 * **空指针**: 解引用 `weak_ptr` 前必须通过 `lock()` 获取 `shared_ptr` == 与其它智能指针对比 == {| class="wikitable" |- ! 指针类型 !! 所有权 !! 是否影响生命周期 !! 主要用途 |- | `unique_ptr` || 独占所有权 || 是 || 单一所有者场景 |- | `shared_ptr` || 共享所有权 || 是 || 多所有者场景 |- | `weak_ptr` || 无所有权 || 否 || 解决循环引用/观察资源 |} == 高级主题 == === 自定义删除器 === `weak_ptr` 可以观察带有自定义删除器的 `shared_ptr`: <syntaxhighlight lang="cpp"> auto deleter = [](int* p) { std::cout << "Custom delete\n"; delete p; }; std::shared_ptr<int> shared(new int(10), deleter); std::weak_ptr<int> weak(shared); </syntaxhighlight> === 继承关系 === `weak_ptr` 支持派生类到基类的转换: <syntaxhighlight lang="cpp"> struct Base {}; struct Derived : Base {}; std::shared_ptr<Derived> d = std::make_shared<Derived>(); std::weak_ptr<Base> b = d; // 隐式转换 </syntaxhighlight> == 常见问题 == === 何时使用 weak_ptr === * 当需要观察对象但不应延长其生命周期时 * 解决可能产生循环引用的设计场景 * 实现缓存、观察者等模式 === weak_ptr 能否单独使用 === 不能。`weak_ptr` 必须与 `shared_ptr` 配合使用,不能直接管理内存。 == 总结 == `std::weak_ptr` 是 C++ 内存管理工具链中的重要组成部分,它: * 解决了 `shared_ptr` 的循环引用问题 * 提供了安全观察共享对象的方式 * 不会增加引用计数,不影响对象生命周期 * 必须通过 `lock()` 方法访问实际对象 正确使用 `weak_ptr` 可以显著提高 C++ 程序的资源管理安全性和设计灵活性。 <mermaid> graph LR A[shared_ptr] -->|构造/赋值| B[weak_ptr] B -->|lock| C[shared_ptr] C -->|解引用| D[访问对象] B -->|expired| E[检查对象状态] </mermaid> [[Category:编程语言]] [[Category:C++]] [[Category:C++ 内存管理]]
摘要:
请注意,所有对代码酷的贡献均被视为依照知识共享署名-非商业性使用-相同方式共享发表(详情请见
代码酷:著作权
)。如果您不希望您的文字作品被随意编辑和分发传播,请不要在此提交。
您同时也向我们承诺,您提交的内容为您自己所创作,或是复制自公共领域或类似自由来源。
未经许可,请勿提交受著作权保护的作品!
取消
编辑帮助
(在新窗口中打开)