跳转到内容
主菜单
主菜单
移至侧栏
隐藏
导航
首页
最近更改
随机页面
MediaWiki帮助
代码酷
搜索
搜索
中文(中国大陆)
外观
创建账号
登录
个人工具
创建账号
登录
未登录编辑者的页面
了解详情
贡献
讨论
编辑“︁
C++ 智能指针详解
”︁
页面
讨论
大陆简体
阅读
编辑
编辑源代码
查看历史
工具
工具
移至侧栏
隐藏
操作
阅读
编辑
编辑源代码
查看历史
常规
链入页面
相关更改
特殊页面
页面信息
外观
移至侧栏
隐藏
您的更改会在有权核准的用户核准后向读者展示。
警告:
您没有登录。如果您进行任何编辑,您的IP地址会公开展示。如果您
登录
或
创建账号
,您的编辑会以您的用户名署名,此外还有其他益处。
反垃圾检查。
不要
加入这个!
= C++智能指针详解 = 智能指针是C++中用于自动化内存管理的工具,它们通过封装原始指针并提供自动内存释放机制,帮助开发者避免内存泄漏、悬垂指针等问题。C++标准库提供了多种智能指针类型,每种适用于不同的场景。 == 智能指针概述 == 智能指针是类模板,它们的行为类似于指针,但在生命周期结束时自动释放所管理的内存。C++11引入了以下主要智能指针类型: * <code>std::unique_ptr</code> - 独占所有权指针 * <code>std::shared_ptr</code> - 共享所有权指针 * <code>std::weak_ptr</code> - 弱引用指针(配合shared_ptr使用) 传统C++中使用<code>new</code>和<code>delete</code>手动管理内存容易出错: <syntaxhighlight lang="cpp"> void problematicFunction() { int* rawPtr = new int(42); // 分配内存 // ...使用指针... if (someCondition) { return; // 内存泄漏! } delete rawPtr; // 必须记得释放 } </syntaxhighlight> 智能指针解决了这个问题: <syntaxhighlight lang="cpp"> #include <memory> void safeFunction() { std::unique_ptr<int> smartPtr(new int(42)); // ...使用指针... if (someCondition) { return; // 内存自动释放 } // 不需要手动delete } </syntaxhighlight> == std::unique_ptr == 独占所有权指针,保证同一时间只有一个unique_ptr指向特定对象。 === 基本用法 === <syntaxhighlight lang="cpp"> #include <memory> #include <iostream> int main() { // 创建unique_ptr std::unique_ptr<int> ptr1(new int(10)); // 使用get()获取原始指针 std::cout << *ptr1.get() << std::endl; // 输出: 10 // 重置指针 ptr1.reset(new int(20)); // 自动释放之前的int(10) // 移动语义(所有权转移) std::unique_ptr<int> ptr2 = std::move(ptr1); if (!ptr1) { std::cout << "ptr1 is now empty" << std::endl; } return 0; } </syntaxhighlight> === 所有权转移示意图 === <mermaid> graph LR A[unique_ptr1 拥有对象] -->|move| B[unique_ptr2 拥有对象] A --> C[unique_ptr1 变为空] </mermaid> == std::shared_ptr == 共享所有权指针,多个shared_ptr可以指向同一对象,使用引用计数管理生命周期。 === 基本用法 === <syntaxhighlight lang="cpp"> #include <memory> #include <iostream> class MyClass { public: MyClass() { std::cout << "MyClass constructed\n"; } ~MyClass() { std::cout << "MyClass destroyed\n"; } }; int main() { // 创建shared_ptr std::shared_ptr<MyClass> ptr1(new MyClass()); { // 复制构造,引用计数增加 std::shared_ptr<MyClass> ptr2 = ptr1; std::cout << "Reference count: " << ptr2.use_count() << std::endl; // 输出: 2 } // ptr2析构,引用计数减1 std::cout << "Reference count: " << ptr1.use_count() << std::endl; // 输出: 1 return 0; // ptr1析构,引用计数为0,对象被销毁 } </syntaxhighlight> === 引用计数机制 === <mermaid> graph TD A[对象] --> B[shared_ptr1] A --> C[shared_ptr2] A --> D[shared_ptr3] B --> E[引用计数=3] </mermaid> == std::weak_ptr == 弱引用指针,不增加引用计数,用于解决shared_ptr的循环引用问题。 === 循环引用问题示例 === <syntaxhighlight lang="cpp"> #include <memory> #include <iostream> class Node { public: 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; node2->next = node1; // 循环引用,内存泄漏 return 0; } </syntaxhighlight> === 使用weak_ptr解决 === <syntaxhighlight lang="cpp"> class SafeNode { public: std::weak_ptr<SafeNode> next; // 使用weak_ptr打破循环 ~SafeNode() { std::cout << "SafeNode destroyed\n"; } }; int main() { auto node1 = std::make_shared<SafeNode>(); auto node2 = std::make_shared<SafeNode>(); node1->next = node2; node2->next = node1; // 不会造成循环引用 return 0; // 对象正常销毁 } </syntaxhighlight> == 智能指针创建方法 == 推荐使用<code>std::make_shared</code>和<code>std::make_unique</code>(C++14): <syntaxhighlight lang="cpp"> auto ptr1 = std::make_shared<int>(42); // 推荐 auto ptr2 = std::make_unique<double>(3.14); // C++14 // 而非: std::shared_ptr<int> ptr3(new int(42)); // 不推荐,可能造成内存泄漏 </syntaxhighlight> == 性能考虑 == * <code>unique_ptr</code>几乎无额外开销 * <code>shared_ptr</code>有引用计数开销 * <code>make_shared</code>通常比直接构造更高效 == 实际应用案例 == === 资源管理 === <syntaxhighlight lang="cpp"> class FileHandler { private: std::unique_ptr<FILE, decltype(&fclose)> file_; public: FileHandler(const char* filename, const char* mode) : file_(fopen(filename, mode), &fclose) { if (!file_) throw std::runtime_error("File open failed"); } // 自动调用fclose }; </syntaxhighlight> === 工厂模式 === <syntaxhighlight lang="cpp"> class Shape { public: virtual ~Shape() = default; virtual void draw() = 0; }; class Circle : public Shape { public: void draw() override { std::cout << "Drawing circle\n"; } }; std::unique_ptr<Shape> createShape() { return std::make_unique<Circle>(); } </syntaxhighlight> == 常见问题 == === 智能指针能否用于数组? === 可以,但需要指定删除器或使用C++17的数组版本: <syntaxhighlight lang="cpp"> // C++11/14方式 std::unique_ptr<int[]> arr(new int[10]); std::shared_ptr<int> arr2(new int[10], std::default_delete<int[]>()); // C++17方式 std::shared_ptr<int[]> arr3(new int[10]); </syntaxhighlight> === 何时使用原始指针? === 智能指针不适用于: 1. 需要与C API交互时 2. 性能极端敏感的场景 3. 需要指针算术运算时 == 总结 == 智能指针类型选择指南: * 优先使用<code>unique_ptr</code> - 简单、高效 * 需要共享所有权时使用<code>shared_ptr</code> * 需要观察但不拥有对象时使用<code>weak_ptr</code> * 避免混合使用智能指针和原始指针 智能指针大大简化了C++内存管理,是现代C++编程中不可或缺的工具。 [[Category:编程语言]] [[Category:C++]] [[Category:C++ 内存管理]]
摘要:
请注意,所有对代码酷的贡献均被视为依照知识共享署名-非商业性使用-相同方式共享发表(详情请见
代码酷:著作权
)。如果您不希望您的文字作品被随意编辑和分发传播,请不要在此提交。
您同时也向我们承诺,您提交的内容为您自己所创作,或是复制自公共领域或类似自由来源。
未经许可,请勿提交受著作权保护的作品!
取消
编辑帮助
(在新窗口中打开)