在C++中,unique_ptr和shared_ptr是两种重要的智能指针,主要区别如下:
1. 所有权机制
-
unique_ptr(独占指针)采用独占所有权 模式,同一时刻只能有一个
unique_ptr指向资源,不可复制(copy禁止),仅支持移动语义 (move)。
示例:cppstd::unique_ptr<int> ptr1 = std::make_unique<int>(10); std::unique_ptr<int> ptr2 = std::move(ptr1); // ptr1所有权转移至ptr2 -
shared_ptr(共享指针)采用共享所有权 模式,多个
shared_ptr可指向同一资源,通过引用计数 管理资源生命周期。
示例:cppstd::shared_ptr<int> ptr1 = std::make_shared<int>(20); std::shared_ptr<int> ptr2 = ptr1; // 引用计数+1
2. 实现原理
-
unique_ptr无额外开销,仅封装原始指针,通过删除器 (默认为
delete)释放资源。
内存占用 :接近原始指针大小(通常为sizeof(void*))。 -
shared_ptr维护控制块 (含引用计数、弱计数、删除器等),资源释放需计数归零。
内存占用:通常为两个指针大小(指向资源和控制块)。
3. 使用场景
-
unique_ptr适用场景- 资源独占管理(如工厂模式返回值)
- 替代
auto_ptr(已废弃) - 性能敏感场景(无计数开销)
-
shared_ptr适用场景- 跨作用域共享资源(如多线程数据传递)
- 复杂所有权关系(如网状数据结构)
- 需自动管理生命周期时
4. 性能对比
| 特性 | unique_ptr |
shared_ptr |
|---|---|---|
| 复制开销 | 禁止复制 | 原子操作更新计数 |
| 内存占用 | 低(1指针) | 较高(2指针+控制块) |
| 线程安全 | 非原子操作 | 引用计数原子操作 |
5. 代码示例对比
cpp
// unique_ptr:所有权转移
std::unique_ptr<int> u1 = std::make_unique<int>(5);
std::unique_ptr<int> u2 = std::move(u1); // u1变为nullptr
// shared_ptr:共享所有权
std::shared_ptr<int> s1 = std::make_shared<int>(10);
{
std::shared_ptr<int> s2 = s1; // 计数=2
} // s2析构,计数=1
总结
- 需独占资源 时用
unique_ptr(高效、轻量) - 需共享资源 时用
shared_ptr(灵活、安全) - 避免循环引用(
shared_ptr可能需配合weak_ptr)