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

【C++】C++智能指针详解

文章目录

      • C++智能指针详解
        • 1. 智能指针的概念
        • 2. std::unique_ptr
        • 3. `std::shared_ptr`
        • 4. `std::weak_ptr`
        • 5. 小结

C++智能指针详解

C++中的智能指针是现代C++编程中管理动态内存的关键工具。智能指针不仅能够帮助开发者自动管理内存,还能避免常见的内存泄漏问题。本文将详细介绍C++中三种常见的智能指针:std::unique_ptrstd::shared_ptrstd::weak_ptr

1. 智能指针的概念

在传统的C++编程中,动态分配的内存需要通过newdelete进行手动管理。然而,如果在程序中忘记调用delete来释放内存,或者delete操作没有在正确的时间点执行,就会导致内存泄漏。智能指针通过自动管理资源的生命周期,简化了这一过程。

智能指针是<memory>头文件中的类模板,负责封装原始指针,并在其生命周期结束时自动释放资源。这样,开发者无需手动管理内存的释放,大大降低了出现内存泄漏的风险。

2. std::unique_ptr

std::unique_ptr是一种独占所有权的智能指针,这意味着某一时刻只能有一个std::unique_ptr实例指向某个动态分配的对象。当std::unique_ptr对象被销毁时,它所管理的对象也会被自动销毁。

#include <iostream>
#include <memory>int main() {std::unique_ptr<int> ptr1 = std::make_unique<int>(10);std::cout << "ptr1指向的值: " << *ptr1 << std::endl;// std::unique_ptr<int> ptr2 = ptr1;  // 错误,unique_ptr不能被拷贝std::unique_ptr<int> ptr2 = std::move(ptr1);  // 可以通过std::move转移所有权if (!ptr1) {std::cout << "ptr1为空,所有权已转移" << std::endl;}std::cout << "ptr2指向的值: " << *ptr2 << std::endl;return 0;
}

在上述代码中,ptr1最初拥有内存对象的所有权,但在所有权转移给ptr2后,ptr1变为空。

3. std::shared_ptr

std::shared_ptr是一种共享所有权的智能指针,可以让多个指针同时指向同一个对象。当最后一个引用该对象的std::shared_ptr被销毁时,才会释放对象的内存。它使用引用计数(reference counting)来追踪有多少shared_ptr实例共享同一个对象。

#include <iostream>
#include <memory>int main() {std::shared_ptr<int> ptr1 = std::make_shared<int>(20);std::shared_ptr<int> ptr2 = ptr1;std::cout << "ptr1的引用计数: " << ptr1.use_count() << std::endl;std::cout << "ptr2的引用计数: " << ptr2.use_count() << std::endl;ptr1.reset();  // ptr1不再管理对象std::cout << "ptr1重置后,ptr2的引用计数: " << ptr2.use_count() << std::endl;return 0;
}

此示例展示了shared_ptr如何共享对象的所有权,并通过引用计数来管理对象的生命周期。

4. std::weak_ptr

std::weak_ptr是一种不拥有对象所有权的智能指针,它与shared_ptr结合使用,可以打破循环引用(circular reference)的问题。循环引用是指两个或多个shared_ptr对象相互引用对方,导致引用计数永远不会为零,从而无法释放内存。

std::weak_ptr不会影响对象的引用计数,因此它不会阻止对象的销毁。要访问weak_ptr管理的对象,必须首先将其转换为shared_ptr

#include <iostream>
#include <memory>struct Node {std::shared_ptr<Node> next;std::weak_ptr<Node> prev;~Node() { std::cout << "Node 被销毁" << std::endl; }
};int main() {std::shared_ptr<Node> node1 = std::make_shared<Node>();std::shared_ptr<Node> node2 = std::make_shared<Node>();node1->next = node2;node2->prev = node1;  // 使用weak_ptr避免循环引用return 0;
}

在这个例子中,如果prevshared_ptr,那么node1node2会相互引用,导致内存无法释放。通过将prev声明为weak_ptr,我们避免了循环引用。

5. 小结

智能指针是C++管理动态内存的强大工具。通过使用std::unique_ptrstd::shared_ptrstd::weak_ptr,程序员可以有效地管理内存的分配与释放,减少内存泄漏的风险,并在需要时打破循环引用。掌握智能指针的使用是现代C++编程的基础,这不仅能提升代码的健壮性,还能使代码更加易于维护。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • VUE3 使用 <transition> 实现组件切换的过渡效果
  • 【日常记录-Linux】WebDriver
  • 如何打造抗冲击的超级电容器?用啥材料好?
  • 大数据技术概述
  • U盘常规数据恢复深度解析:原因、方案与预防策略
  • 文件包含PHP伪协议利用方法
  • c++(list)
  • CSS学习4[重点]
  • 原油市场“闪崩”,国际油价单日下跌超4%!
  • 一. 从Hive开始
  • 坑——fastjson将字符串转到带枚举的java对象
  • 【多线程】阻塞,忙等待,睡眠,挂起的简单理解,以及各自优缺点
  • Spring框架——springweb(一篇包会)
  • C#——XML序列化
  • 网络安全服务基础Windows--第9节-DNS部署与安全
  • 【前端学习】-粗谈选择器
  • leetcode46 Permutation 排列组合
  • Linux各目录及每个目录的详细介绍
  • Python 使用 Tornado 框架实现 WebHook 自动部署 Git 项目
  • SegmentFault 技术周刊 Vol.27 - Git 学习宝典:程序员走江湖必备
  • Spark VS Hadoop:两大大数据分析系统深度解读
  • 检测对象或数组
  • 设计模式(12)迭代器模式(讲解+应用)
  • 运行时添加log4j2的appender
  • 栈实现走出迷宫(C++)
  • TPG领衔财团投资轻奢珠宝品牌APM Monaco
  • 大数据全解:定义、价值及挑战
  • ​LeetCode解法汇总2696. 删除子串后的字符串最小长度
  • ​马来语翻译中文去哪比较好?
  • #if和#ifdef区别
  • #Z0458. 树的中心2
  • (1/2) 为了理解 UWP 的启动流程,我从零开始创建了一个 UWP 程序
  • (2)空速传感器
  • (JSP)EL——优化登录界面,获取对象,获取数据
  • (附源码)计算机毕业设计SSM基于java的云顶博客系统
  • (论文阅读26/100)Weakly-supervised learning with convolutional neural networks
  • (收藏)Git和Repo扫盲——如何取得Android源代码
  • (五)activiti-modeler 编辑器初步优化
  • (一)项目实践-利用Appdesigner制作目标跟踪仿真软件
  • (转)eclipse内存溢出设置 -Xms212m -Xmx804m -XX:PermSize=250M -XX:MaxPermSize=356m
  • (转载)Google Chrome调试JS
  • .equal()和==的区别 怎样判断字符串为空问题: Illegal invoke-super to void nio.file.AccessDeniedException
  • .NET Framework Client Profile - a Subset of the .NET Framework Redistribution
  • .netcore 获取appsettings
  • /etc/fstab和/etc/mtab的区别
  • @private @protected @public
  • @property括号内属性讲解
  • @RequestMapping 和 @GetMapping等子注解的区别及其用法
  • [2019红帽杯]Snake
  • [202209]mysql8.0 双主集群搭建 亲测可用
  • [Algorithm][动态规划][01背包问题][目标和][最后一块石头的重量Ⅱ]详细讲解
  • [BeginCTF]真龙之力
  • [CareerCup] 12.3 Test Move Method in a Chess Game 测试象棋游戏中的移动方法
  • [EFI]Atermiter X99 Turbo D4 E5-2630v3电脑 Hackintosh 黑苹果efi引导文件
  • [Java][算法 双指针]Day 02---LeetCode 热题 100---04~07