深入理解 C++ 智能指针:原理、实现与最佳实践
·
智能指针概述
智能指针本质上是封装了裸指针的类,通过 RAII(资源获取即初始化)管理资源生命周期。
常见智能指针:
std::unique_ptr:独占所有权,不能复制,只能移动。std::shared_ptr:共享所有权,引用计数管理。std::weak_ptr:弱引用,不增加引用计数,用于解决循环引用。
三、std::unique_ptr
3.1 基本用法
代码语言:javascript
AI代码解释
cpp复制编辑std::unique_ptr<int> p1(new int(10));
// p1 拥有指针
3.2 独占所有权
代码语言:javascript
AI代码解释
cpp复制编辑std::unique_ptr<int> p2 = std::move(p1);
// p1 失效,p2 拥有所有权
3.3 自动释放机制
智能指针析构时调用 delete 释放内存,避免泄漏。
3.4 自定义删除器
代码语言:javascript
AI代码解释
cpp复制编辑std::unique_ptr<FILE, decltype(&fclose)> fp(fopen("file.txt", "r"), &fclose);
支持管理非 new 分配资源。
四、std::shared_ptr
4.1 引用计数机制
shared_ptr 内部维护两个计数:
- 强引用计数:当前持有所有权的
shared_ptr数量 - 弱引用计数:
weak_ptr数量
计数为零时释放资源。
4.2 典型用法
代码语言:javascript
AI代码解释
cpp复制编辑std::shared_ptr<int> sp1 = std::make_shared<int>(20);
std::shared_ptr<int> sp2 = sp1; // 引用计数 +1
4.3 控制块(Control Block)
实际实现中,资源指针和引用计数放在控制块里,实现高效管理。
4.4 循环引用问题
若两个对象互相持有 shared_ptr,会导致内存泄漏。
五、std::weak_ptr
5.1 弱引用
weak_ptr 不拥有对象所有权,不影响引用计数。
5.2 解决循环引用
代码语言:javascript
AI代码解释
cpp复制编辑struct B;
struct A {
std::shared_ptr<B> b_ptr;
};
struct B {
std::weak_ptr<A> a_ptr; // 弱引用避免循环
};
5.3 lock() 获取 shared_ptr
通过 lock() 检查资源是否还存活。
六、智能指针的内部实现原理
6.1 Control Block 结构
- 持有资源指针
- 强引用计数
- 弱引用计数
- 删除器指针(自定义删除器)
6.2 引用计数操作
线程安全的计数增加和减少,通常使用原子操作。
七、最佳实践
7.1 优先使用 make_shared 和 make_unique
make_shared在一块内存中分配对象和控制块,提高性能。- 避免裸
new。
7.2 使用 unique_ptr 表达独占语义
避免无谓的引用计数开销。
7.3 注意循环引用
用 weak_ptr 打破循环。
7.4 自定义删除器管理非内存资源
管理文件、socket 等资源。
八、性能考量
shared_ptr的引用计数增加和减少有一定开销。unique_ptr开销最小。- 不恰当的过度共享会导致性能下降。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐

所有评论(0)