智能指针是一种在 C++ 中管理动态分配内存的工具,可以帮助避免内存泄漏和提高程序的安全性。在 C++11 标准引入之后,C++ 提供了三种主要类型的智能指针,它们分别是 std::unique_ptr
、std::shared_ptr
和 std::weak_ptr
。这些智能指针有不同的所有权管理方式和适用场景。
1. std::unique_ptr
- 独占所有权 :
std::unique_ptr
管理其所指向的对象,并且独占对该对象的访问权限。 - 特点 :不能被复制,但可以通过移动语义转移所有权。当
std::unique_ptr
被销毁时,它所管理的对象也会被自动销毁。 - 适用场景:适用于需要独占所有权且生命周期明确的场景,如避免内存泄漏的最佳选择。
cpp
std::unique_ptr<int> ptr = std::make_unique<int>(10);
2. std::shared_ptr
- 共享所有权 :
std::shared_ptr
允许多个指针共享同一个对象。它维护一个引用计数,当最后一个std::shared_ptr
被销毁时,其所管理的对象被释放。 - 特点:可以被复制和赋值,引用计数递增和递减是自动管理的。
- 适用场景:适用于多个指针需要访问同一对象的场景,如数据结构的节点。
cpp
std::shared_ptr<int> ptr1 = std::make_shared<int>(20);
std::shared_ptr<int> ptr2 = ptr1; // 引用计数增加
3. std::weak_ptr
- 弱引用 :
std::weak_ptr
是为了解决std::shared_ptr
的循环引用问题而引入的。它不增加引用计数,只是提供了对所指向对象的非拥有访问权限。 - 特点 :不能直接访问对象,需要通过
lock()
方法转换为std::shared_ptr
才能访问对象。 - 适用场景 :主要用于避免
std::shared_ptr
循环引用导致的内存泄漏,例如图结构或者双向引用场景。
cpp
std::shared_ptr<int> shared = std::make_shared<int>(30);
std::weak_ptr<int> weak = shared;
if (auto sharedPtr = weak.lock()) {
// 使用 sharedPtr 访问对象
} else {
// 对象已经被销毁
}
区别总结
- 所有权管理 :
std::unique_ptr
独占所有权,std::shared_ptr
共享所有权,std::weak_ptr
不影响所有权。 - 复制和赋值 :
std::unique_ptr
不能复制,只能移动;std::shared_ptr
可以复制和赋值;std::weak_ptr
不能直接访问对象,需要通过lock()
方法转换为std::shared_ptr
才能访问。 - 线程安全 :
std::shared_ptr
在多线程环境下使用时需要考虑引用计数的线程安全性,而std::weak_ptr
可以避免循环引用导致的内存泄漏。
选择合适的智能指针取决于所需的所有权模型和对象生命周期管理策略。