在 C++ 中,std::unique_ptr
、std::shared_ptr
和 std::weak_ptr
是 智能指针(Smart Pointers),它们定义在 <memory>
头文件中,用于自动管理动态分配的内存资源,帮助开发者避免内存泄漏和手动 delete
指针带来的问题。
下面是这三种智能指针的简要介绍和区别:
1. std::unique_ptr
- 独占所有权(Exclusive ownership)
- 同一时间只能有一个
unique_ptr
指向某个资源。 - 不能复制(拷贝构造函数和拷贝赋值运算符被删除),但可以移动(move)。
- 当
unique_ptr
被销毁时,它所管理的对象也会被自动删除。
示例:
std::unique_ptr<int> ptr1 = std::make_unique<int>(10);
// std::unique_ptr<int> ptr2 = ptr1; // 编译错误:不允许拷贝
std::unique_ptr<int> ptr2 = std::move(ptr1); // OK:转移所有权
使用场景:
- 确保只有一个智能指针对资源拥有所有权。
- 避免共享导致的复杂生命周期管理。
2. std::shared_ptr
- 共享所有权(Shared ownership)
- 多个
shared_ptr
可以指向同一个对象。 - 内部使用引用计数(reference count),当最后一个
shared_ptr
被销毁时,资源才会释放。 - 支持拷贝和赋值。
示例:
std::shared_ptr<int> ptr1 = std::make_shared<int>(20);
std::shared_ptr<int> ptr2 = ptr1; // OK:引用计数增加
使用场景:
- 多个对象或模块需要共享一个资源。
- 生命周期不确定,需自动管理。
3. std::weak_ptr
- 弱引用(Weak reference)
- 不拥有资源,也不影响资源的生命周期。
- 必须与
shared_ptr
搭配使用,用来观察某个由shared_ptr
管理的对象。 - 用于解决循环引用问题(如 A 持有 B 的 shared_ptr,B 持有 A 的 shared_ptr)。
示例:
std::shared_ptr<int> shared = std::make_shared<int>(30);
std::weak_ptr<int> weakPtr = shared;
if (auto spt = weakPtr.lock()) { // 获取临时 shared_ptr
std::cout << *spt << std::endl;
} else {
std::cout << "对象已被释放" << std::endl;
}
使用场景:
- 观察对象但不控制其生命周期。
- 解决
shared_ptr
循环引用问题。
📊 总结对比表:
特性 | std::unique_ptr | std::shared_ptr | std::weak_ptr |
---|---|---|---|
所有权模型 | 独占 | 共享 | 弱引用(无所有权) |
是否可拷贝 | ❌ | ✅ | ✅(但不会增加引用计数) |
是否可移动 | ✅ | ✅ | ✅ |
自动释放资源 | ✅ | ✅ | ❌(需通过 lock() 获取 shared_ptr) |
是否支持数组 | ✅(C++17 起) | ✅(C++20 起推荐使用) | ✅(需配合 shared_ptr 使用) |
✅ 推荐使用顺序(优先级):
- 优先使用
std::unique_ptr
:最轻量、安全、高效。 - 如果确实需要共享所有权,使用
std::shared_ptr
。 - 若只是观察或打破循环依赖,使用
std::weak_ptr
。