C++ unique_ptr与shared_ptr的区别_C++11智能指针选择指南

9次阅读

unique_ptr 独占所有权、无性能开销,适用于单一所有者场景;shared_ptr 共享所有权、有引用计数开销,适用于多所有者或需延长生命周期的场景。

C++ unique_ptr 与 shared_ptr 的区别_C++11 智能指针选择指南

unique_ptrshared_ptr 是 C++11 中两种核心的智能指针,它们都用于自动管理动态分配的对象生命周期,避免内存泄漏。但二者在所有权语义和性能上存在本质 区别,选择哪种取决于具体使用场景。

所有权模型不同

unique_ptr 表达的是独占所有权。一个 unique_ptr 对象独占其所指向的资源,不能被复制。如果需要转移所有权,必须通过 std::move 实现。

例如:

std::unique_ptr ptr1 = std::make_unique(42); // 错误:不允许复制 // std::unique_ptr ptr2 = ptr1; // 正确:通过 move 转移所有权 std::unique_ptr ptr2 = std::move(ptr1);

shared_ptr 支持共享所有权。多个 shared_ptr 可以指向同一个对象,内部使用引用计数来跟踪有多少个指针共享该资源。当最后一个 shared_ptr 被销毁时,对象才被释放。

例如:

std::shared_ptr sptr1 = std::make_shared(100); std::shared_ptr sptr2 = sptr1; // 引用计数加 1 // 两者共享同一块内存

性能与开销对比

unique_ptr 几乎没有运行时开销。它生成的代码通常与原始指针一样高效,因为所有权是静态确定的,不需要额外数据结构。

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

shared_ptr 有明显开销。每个 shared_ptr 都维护一个控制块,包含引用计数、弱引用计数和删除器等信息。每次拷贝和析构都需要原子操作更新引用计数,在多线程环境中影响性能。

因此,在不需要共享的场景下优先使用 unique_ptr。

适用场景建议

使用 unique_ptr 的情况:

  • 类成员变量持有独占资源(如文件句柄、网络连接)
  • 工厂函数返回新创建的对象
  • 容器中存储动态对象,且不需共享
  • 替代裸指针作为函数参数或返回值,表达明确的所有权转移

使用 shared_ptr 的情况:

  • 多个对象或模块需要共享同一资源
  • 无法确定哪个使用者最后释放资源
  • 实现观察者模式、回调机制等需要延长对象生命周期的场景
  • 配合 weak_ptr 解决循环引用问题

如何选择?

从设计原则出发:优先考虑是否需要共享。大多数情况下,资源应由单一所有者管理,这时选 unique_ptr。只有确实需要多个所有者时才使用 shared_ptr。

如果需要将 unique_ptr 升级为共享所有权,可以通过 move 构造 shared_ptr:

std::unique_ptr up = std::make_unique(50); std::shared_ptr sp = std::move(up); // 合法转换

基本上就这些。unique_ptr 更轻量、安全,适合绝大多数场景;shared_ptr 提供灵活性,但带来开销和潜在的循环引用风险。合理选择能提升代码效率与可维护性。

text=ZqhQzanResources