C++ 智能指针详解: std::unique_ptr 和 std::shared_ptr
C++11引入了智能指针,它们是管理动态分配内存的强大工具。本文将详细介绍两种最常用的智能指针: std::unique_ptr
和 std::shared_ptr
。
std::unique_ptr
概述
std::unique_ptr
是一种独占所有权的智能指针。它确保一个对象只能被一个 unique_ptr
所拥有,这意味着不能复制 unique_ptr
,只能移动它。
主要特性
- 独占所有权: 一个
unique_ptr
不能被复制,只能被移动。 - 自动释放: 当
unique_ptr
离开作用域时,它所管理的对象会被自动删除。 - 零开销: 在大多数操作中,
unique_ptr
与原始指针的性能相当。 - 自定义删除器: 可以指定自定义的删除方式。
示例代码
#include <iostream> #include <memory> class MyClass { public: MyClass() { std::cout << "MyClass constructed\n"; } ~MyClass() { std::cout << "MyClass destructed\n"; } void doSomething() { std::cout << "Doing something\n"; } }; int main() { // 创建unique_ptr std::unique_ptr<MyClass> ptr1 = std::make_unique<MyClass>(); // 使用->访问成员 ptr1->doSomething(); // 无法复制unique_ptr // std::unique_ptr<MyClass> ptr2 = ptr1; // 编译错误 // 可以移动unique_ptr std::unique_ptr<MyClass> ptr2 = std::move(ptr1); // ptr1现在为空 if (ptr1 == nullptr) { std::cout << "ptr1 is null\n"; } // ptr2现在拥有对象 ptr2->doSomething(); // 离开作用域时,ptr2自动删除对象 }
std::shared_ptr
概述
std::shared_ptr
是一种共享所有权的智能指针。多个 shared_ptr
可以指向同一个对象,对象的内存会在最后一个引用被销毁时释放。
主要特性
- 共享所有权: 多个
shared_ptr
可以指向同一个对象。 - 引用计数: 内部维护一个引用计数,当计数降为0时删除对象。
- 线程安全: 引用计数的增减是原子操作,但对象本身的访问不是线程安全的。
- 可以从 this 指针创建: 可以安全地从一个对象的成员函数中创建指向 this 的
shared_ptr
。
示例代码
#include <iostream> #include <memory> class SharedClass : public std::enable_shared_from_this<SharedClass> { public: SharedClass() { std::cout << "SharedClass constructed\n"; } ~SharedClass() { std::cout << "SharedClass destructed\n"; } std::shared_ptr<SharedClass> getShared() { return shared_from_this(); } }; int main() { // 创建shared_ptr auto ptr1 = std::make_shared<SharedClass>(); { // 创建另一个指向同一对象的shared_ptr std::shared_ptr<SharedClass> ptr2 = ptr1; std::cout << "使用计数: " << ptr1.use_count() << std::endl; // 输出 2 // 从对象内部获取shared_ptr auto ptr3 = ptr1->getShared(); std::cout << "使用计数: " << ptr1.use_count() << std::endl; // 输出 3 // ptr2和ptr3离开作用域,但对象不会被删除 } std::cout << "使用计数: " << ptr1.use_count() << std::endl; // 输出 1 // ptr1离开作用域,对象被删除 }
比较 unique_ptr 和 shared_ptr
特性 | std::unique_ptr | std::shared_ptr |
---|---|---|
所有权 | 独占 | 共享 |
复制 | 不允许 | 允许 |
移动 | 允许 | 允许 |
引用计数 | 无 | 有 |
性能开销 | 几乎为零 | 有一定开销 |
内存使用 | 与原始指针相同 | 额外内存用于控制块 |
线程安全 | 不适用 | 引用计数操作是安全的 |
循环引用 | 不会发生 | 可能发生,需要注意 |
最佳实践
- 优先使用
std::unique_ptr
,除非确实需要共享所有权。 - 使用
std::make_unique
和std::make_shared
来创建智能指针。 - 避免使用裸指针,尽可能使用智能指针。
- 注意避免
std::shared_ptr
的循环引用问题,必要时使用std::weak_ptr
。 - 在类的公共接口中返回
std::unique_ptr
来转移所有权。 - 在需要共享但不参与所有权的场景中使用
std::weak_ptr
。
std::unique_ptr
和 std::shared_ptr
是C++中管理动态内存的强大工具。正确使用这些智能指针可以大大减少内存泄漏的风险,提高代码的安全性和可维护性。理解它们的特性和适用场景对于编写高质量的C++程序至关重要。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)