当前位置: 首页 > news >正文

智能指针:C++内存管理的利器

目录

为什么需要智能指针?

内存泄漏的危害

智能指针的原理与使用

C++中的智能指针类型

线程安全问题

自定义删除器

C++11与Boost的关系

总结


为什么需要智能指针?

在C++中,手动管理内存一直是一个容易出错的问题。考虑以下代码:


 

void Func() {int* p1 = new int;int* p2 = new int;cout << div() << endl;  // 可能抛出异常delete p1;delete p2;
}

如果`div()`函数抛出异常,`delete`语句将不会被执行,导致内存泄漏。这就是智能指针要解决的问题。

内存泄漏的危害

内存泄漏是指程序未能释放不再使用的内存。长期运行的程序(如操作系统、后台服务)出现内存泄漏会导致:
- 可用内存逐渐减少
- 程序响应变慢
- 最终可能导致系统崩溃

智能指针的原理与使用

智能指针基于RAII(Resource Acquisition Is Initialization)技术:
- 在对象构造时获取资源
- 在对象生命周期内保持资源有效
- 在对象析构时自动释放资源

基本实现


 

template<class T>
class SmartPtr {
public:SmartPtr(T* ptr = nullptr) : _ptr(ptr) {}~SmartPtr() { if(_ptr) delete _ptr; }T& operator*() { return *_ptr; }T* operator->() { return _ptr; }private:T* _ptr;
};


 

C++中的智能指针类型

1. auto_ptr (C++98)


 

auto_ptr<int> sp1(new int);
auto_ptr<int> sp2(sp1);  // 管理权转移,sp1变为空


 

缺点:管理权转移语义不直观,已被弃用。

2. unique_ptr (C++11)


 

unique_ptr<int> sp1(new int);
// unique_ptr<int> sp2(sp1);  // 错误:不允许拷贝


 

特点:
- 简单粗暴地禁止拷贝
- 轻量高效
- 可移动(使用std::move)

3. shared_ptr (C++11)


 

shared_ptr<int> sp1(new int);
shared_ptr<int> sp2(sp1);  // 引用计数增加


 

原理:
- 使用引用计数管理资源
- 最后一个持有者负责释放资源
- 线程安全的引用计数操作

4. weak_ptr (C++11)

用于解决shared_ptr的循环引用问题:


 

struct ListNode {int _data;weak_ptr<ListNode> _prev;weak_ptr<ListNode> _next;
};


 

特点:
- 不增加引用计数
- 需要转换为shared_ptr才能访问资源

线程安全问题

shared_ptr的线程安全分为两方面:
1. 引用计数的操作是线程安全的(内部加锁)
2. 管理的资源本身不是线程安全的,需要额外同步

自定义删除器

对于非new创建的资源,可以指定自定义删除器:
 

// 释放malloc分配的内存
shared_ptr<int> sp1((int*)malloc(4), free);// 释放数组
shared_ptr<int> sp2(new int[10], [](int* p){ delete[] p; });// 关闭文件
shared_ptr<FILE> sp3(fopen("test.txt", "w"), [](FILE* p){ fclose(p); });


 

C++11与Boost的关系

1. C++98引入了auto_ptr(设计不佳)
2. Boost库提出了scoped_ptr、shared_ptr和weak_ptr
3. C++11借鉴Boost设计,引入了:
   - unique_ptr(对应Boost的scoped_ptr)
   - shared_ptr
   - weak_ptr


总结

智能指针是C++现代编程中不可或缺的工具,它们:
- 自动管理内存,防止泄漏
- 提供异常安全保证
- 有明确的语义(独占或共享所有权)
- 能处理各种资源管理场景

在现代C++中,应该尽量避免使用裸指针和手动内存管理,转而使用智能指针来编写更安全、更简洁的代码。

http://www.lryc.cn/news/622437.html

相关文章:

  • c++程序示例:多线程下的实例计数器
  • [HDCTF 2023]Normal_Rsa(revenge)
  • 主流开源实时互动数字人大模型
  • 读书笔记-积极心理学 《心流,最优体验心理学》
  • 条件变量的基本介绍与有界缓冲区问题
  • 小红书帖子评论的nodejs爬虫脚本
  • 补充日志之-配置文件解析指南(Centos7)
  • CAXA电子图板2026(国产CAD之光)
  • 机器学习之PCA
  • pyqt5无法显示opencv绘制文本和掩码信息
  • OpenCV 阈值处理
  • 应用侧华为云LoTDA设备接入平台
  • 重塑工业设备制造格局:明远智睿 T113-i 的破局之道
  • IgH初始化--未接从站
  • 【160页PPT】机械行业数字化生产供应链产品解决方案(附下载方式)
  • 光伏工单智能管理,故障处理快人一步
  • 状态流程框架(cola-component-statemachine)
  • WinForm 简单用户登录记录器实现教程
  • 五、ZooKeeper、Kafka、Hadoop、HBase、Spark、Flink集群化软件的部署
  • Sui 主网升级至 V1.53.2
  • 【DDIA】第三部分:衍生数据
  • 俄罗斯信封套娃问题-二维最长递增子序列
  • day29-进程和线程(2)
  • python自学笔记9 Seaborn可视化
  • 47.分布式事务理论
  • Elasticsearch:使用 Gradio 来创建一个简单的 RAG 应用界面
  • LeetCode刷题记录----236.二叉树的最近公共节点(medium)
  • 终极手撸cpu系列-详解底层原理-CPU硬核解剖:从0和1到 看透CPU逻辑设计内部原理,弄清楚现代多线程cpu工作原理
  • IC(Integrated Circuit,集成电路)是什么?
  • Qt——常用Widget(控件)