在 C++ 中,std::shared_ptr 和 std::unique_ptr 是两种不同的智能指针,它们有不同的所有权语义,不能直接互换,但在特定条件下可以相互转换:
unique_ptr → shared_ptr (✅ 安全)// unique_ptr 可以转换为 shared_ptr(移动语义)
std::unique_ptr<MyClass> unique = std::make_unique<MyClass>();
std::shared_ptr<MyClass> shared = std::move(unique); // 所有权转移
// 此时 unique 变为 nullptr
assert(unique == nullptr);shared_ptr → unique_ptr (❌ 不安全)std::shared_ptr<MyClass> shared = std::make_shared<MyClass>();
// 以下转换是无效的!会编译错误
std::unique_ptr<MyClass> unique = shared; // 错误:没有转换函数shared_ptr 是唯一所有者时if (shared.use_count() == 1) {
// 危险操作:手动释放所有权(不推荐)
MyClass* raw = shared.get();
shared.reset(); // 放弃所有权
std::unique_ptr<MyClass> unique(raw); // 接管所有权
}⚠️ 警告:这种操作非常危险,容易导致双重释放!
特性 | std::unique_ptr | std::shared_ptr |
|---|---|---|
所有权 | 独占所有权 | 共享所有权 |
复制语义 | 不可复制(只能移动) | 可以复制 |
性能开销 | 零开销(等同原始指针) | 有引用计数开销 |
循环引用风险 | 无 | 需要配合 weak_ptr 避免 |
自定义删除器 | 支持(类型安全) | 支持(类型擦除) |
优先使用 unique_ptr
// 默认使用 unique_ptr
auto resource = std::make_unique<Resource>();
// 需要共享时再转换
std::shared_ptr<Resource> shared_res = std::move(resource);需要共享所有权时直接用 shared_ptr
// 明确需要共享的场景
auto shared = std::make_shared<SharedResource>();避免所有权混用 同一资源不应同时被两种智能指针管理。
// unique_ptr → shared_ptr
template<typename T>
std::shared_ptr<T> make_shared_from_unique(std::unique_ptr<T>&& unique) {
return std::shared_ptr<T>(std::move(unique));
}
// shared_ptr → unique_ptr (危险!仅用于特殊情况)
template<typename T>
std::unique_ptr<T> make_unique_from_shared(std::shared_ptr<T> shared) {
if (shared.use_count() != 1) throw std::logic_error("Not exclusive owner!");
return std::unique_ptr<T>(shared.release()); // 需要自定义删除器支持
}unique_ptr → shared_ptr:✅ 安全,通过移动语义实现shared_ptr → unique_ptr:❌ 不安全,应避免shared_ptr