c++中如何使用smart pointers智能指针_c++ unique_ptr与shared_ptr用法

7次阅读

该用 std::unique_ptr 而不是 std::shared_ptr 的核心判断标准是所有权是否需要共享:unique_ptr 表示独占所有权,转移后原指针自动置空;shared_ptr 通过引用计数允许多方共享同一对象。

c++ 中如何使用 smart pointers 智能指针_c++ unique_ptr 与 shared_ptr 用法

什么时候该用 std::unique_ptr 而不是 std::shared_ptr

核心判断标准是所有权是否需要共享:std::unique_ptr 表示独占所有权,转移后原指针自动置空;std::shared_ptr 通过引用计数允许多方共享同一对象。如果只是临时封装堆内存、函数返回资源、或作为容器元素管理单个对象,优先选 unique_ptr —— 它零开销、无原子操作、不引入循环引用风险。

常见误用场景:

  • shared_ptr 当作“更安全的 unique_ptr”随意传参,结果拖慢性能且掩盖设计问题
  • 在类成员中用 shared_ptr 管理本该由类自身生命周期决定的对象(比如内部缓存),导致对象存活时间超出预期
  • 跨线程传递 shared_ptr 但没意识到控制块(control block)的引用计数是原子操作,有轻微开销

unique_ptr 的正确构造与移动语义

unique_ptr 不支持拷贝,只支持移动。直接赋值或传参时若忘记 std::move(),编译器会报错:use of deleted function 'std::unique_ptr::unique_ptr(const std::unique_ptr&)'

推荐写法:

立即学习 C++ 免费学习笔记(深入)”;

  • std::make_unique(……) 构造,避免裸 new 和异常安全问题
  • 函数返回 unique_ptr 时,直接 return std::make_unique(x);,调用方自动接收右值
  • 传入函数时,按值接收(void f(std::unique_ptr p)),表示函数要接管所有权;如只需观察,改用 T*T&
std::unique_ptr p1 = std::make_unique(42); std::unique_ptr p2 = std::move(p1); // ✅ 正确:显式移动 // std::unique_ptr p3 = p1; // ❌ 编译失败 

shared_ptr 的循环引用与 weak_ptr 解法

两个 shared_ptr 相互持有对方管理的对象(例如双向链表节点、父子对象关系),会导致引用计数永远不为 0,内存泄漏。这是 shared_ptr 最典型的陷阱。

解决方式不是少用 shared_ptr,而是识别“观测性引用”并替换为 std::weak_ptr

  • weak_ptr 不增加引用计数,调用 lock() 可尝试升级为 shared_ptr,失败说明对象已销毁
  • 典型模式:父持子用 shared_ptr,子持父用 weak_ptr
  • weak_ptr 本身不保证线程安全,但 lock() 是原子的
struct Node {std::shared_ptr next;     std::weak_ptr prev; // 避免循环引用 };  auto a = std::make_shared(); auto b = std::make_shared(); a->next = b; b->prev = a; // ✅ 不增加 a 的引用计数 

自定义删除器与数组支持的细节差异

unique_ptrshared_ptr 都支持自定义删除器,但语法和默认行为不同:

  • unique_ptr 是合法类型,析构时自动调用 delete[];而 shared_ptr 在 C++17 前不被标准支持,C++17 起才允许,但仍需显式传入 default_delete
  • 自定义删除器类型是 unique_ptr 模板参数的一部分(影响类型),所以 unique_ptr != unique_ptr;而 shared_ptr 的删除器是运行期绑定的,类型不变
  • make_shared 无法指定自定义删除器,必须用裸 new + 构造函数方式
// unique_ptr 数组(推荐)std::unique_ptr arr = std::make_unique(10);  // shared_ptr 数组(C++17+)std::shared_ptr arr2(new int[10], std::default_delete());

真正难的不是记住语法,是每次写 shared_ptr 时多问一句:“这个对象,到底有没有别的地方也该负责它的生死?”——没想清楚就先用 unique_ptr

星耀云
版权声明:本站原创文章,由 星耀云 2025-12-31发表,共计1777字。
转载说明:转载本网站任何内容,请按照转载方式正确书写本站原文地址。本站提供的一切软件、教程和内容信息仅限用于学习和研究目的;不得将上述内容用于商业或者非法用途,否则,一切后果请用户自负。本站信息来自网络,版权争议与本站无关。
text=ZqhQzanResources