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

深入理解 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_sharedmake_unique
  • make_shared在一块内存中分配对象和控制块,提高性能。
  • 避免裸new
7.2 使用unique_ptr表达独占语义

避免无谓的引用计数开销。

7.3 注意循环引用

weak_ptr打破循环。

7.4 自定义删除器管理非内存资源

管理文件、socket 等资源。


八、性能考量

  • shared_ptr的引用计数增加和减少有一定开销。
  • unique_ptr开销最小。
  • 不恰当的过度共享会导致性能下降。
http://www.jsqmd.com/news/820314/

相关文章:

  • 【独家拆解】Sora 2正式版底层架构升级:从DiT-XL到时空联合注意力v3.2,性能提升217%的关键证据
  • 悬而未决:Nacos 与 Apollo 能否终结“改配置就要重启”的诅咒?
  • 如何用MZmine免费开源工具轻松搞定质谱数据分析?新手入门完全指南
  • 电商内容自动化秘籍:构建商品知识库,小白也能轻松掌握大模型自动化(收藏版)
  • 轻量级系统模拟器semu:RISC-V内核开发与调试实战指南
  • QMCDecode终极指南:3分钟解锁QQ音乐加密文件,实现跨平台音乐自由
  • 单片机开发者如何通过Taotoken快速接入大模型API提升代码效率
  • Arduino GSM通信实战:Adafruit FONA模块硬件解析与AT命令编程指南
  • 2026年乌鲁木齐靠谱精装公司top5实践经验案例分享!
  • 网盘下载提速新方案:8大平台直链获取工具全解析
  • MCP服务器开源集市:AI智能体开发者的插件生态与实战指南
  • 汽车电子功能安全:锁步核与ECC技术解析
  • STM32+ESP8266物联网设备一键配网方案详解与腾讯云实践
  • Midjourney API定价突变预警:2024Q3即将关停的免费层+新Tier强制迁移倒计时72小时
  • ElevenLabs古吉拉特文语音合成失效排查手册(97.3%开发者忽略的ISO 639-2语言码陷阱)
  • JavaScript 的基石:彻底搞懂 8 种数据类型
  • 开源容器镜像安全扫描器Quaid:基于Trivy的轻量级CI/CD集成方案
  • 英雄联盟LCU工具集:LeagueAkari终极游戏助手完全指南
  • 运算放大器在扫地机器人硬件设计中的六大关键应用解析
  • AArch64处理器特性寄存器ID_AA64PFR2_EL1详解与应用
  • Adafruit Feather RP2040 Adalogger板载SD卡开发全攻略:从SPI原理到CircuitPython/Arduino实战
  • 量子比特鲁棒控制:噪声抑制与傅里叶脉冲设计
  • CircuitPython开发环境配置:编辑器安全写入与串口调试全平台指南
  • Debian Linux 全网超全快捷键手册:按字面意思死记,新手也能一遍记住
  • BNO085传感器融合IMU实战:从原理到Arduino/Python应用
  • 如何一键搞定NS模拟器安装配置:新手终极解决方案指南
  • 抖音万粉号出售 万粉抖音号价格表
  • Android系统架构中的性能优化与功耗优化策略
  • INA228功率监测模块:从微安到10A的高精度电流电压测量实战
  • I2C总线电气隔离原理与Adafruit ISO1540模块实战指南