RAII 与智能指针

1.什么是 RAII

1.概念
Resource Acquisition Is Initialization 资源获取即初始化。一般分为 3 步,当我们在main函数中声明一个局部对象的时候,会自动调用构造函数进行对象的初始化,当整个main函数执行完成后,自动调用析构函数来销毁对象,整个过程无需人工介入,由操作系统自动完成;

2.如何使用 raii

智能指针(std::shared_ptr和std::unique_ptr)即RAII最具代表的实现,使用智能指针,可以实现自动的内存管理,再也不需要担心忘记delete造成的内存泄漏。

还有就是锁,有可能出现初始化锁但是没有释放锁的情况

2.智能指针

智能指针源码实现

导入头文件

#include <memory>

2.1 内存泄露

一般我们常说的内存泄漏是指堆内存的泄漏。堆内存是指程序从中分配的,大小任意的(内存块的大小可以在程序运行期决定)内存块,使用完后必须显式释放的内存。应用程序般使用malloc,、realloc、 new等函数从堆中分配到块内存,

避免内存泄露的几种方式

  • 计数法:使用new或者malloc时,让该数+1,delete或free时,该数-1,程序执行完打印这个计数,如果不为0则表示存在内存泄露
  • 一定要将基类的析构函数声明为虚函数
~A() = default;
  • 对象数组的释放一定要用delete []
  • 有new就有delete,有malloc就有free,保证它们一定成对出现

检测工具

  • Linux下可以使用Valgrind工具

    https://blog.csdn.net/qq_20553613/article/details/106503929

会显示有几个指针是 free 的有几个指针是 alloc 的,显示是在哪一行出错的,同样 Valgrind 还能检测其他的内存问题:

valgrind --tool=memcheck --leak-check=full ./a

使用空指针

使用野指针:指向了一个根本不存在或者已经被释放的指针

内存空间访问越界

内存空间未释放

内存空间重复释放

内存空间申请和释放不匹配

  • Windows下可以使用CRT库

3.auto_ptr

定义:auto_ptr的实现原理其实就是RAII,在构造的时候获取资源,在析构的时候释放资源,并进行相关指针操作的重载

抛弃原因:因为有拷贝构造和赋值的情况下原有的对象会被释放

https://blog.csdn.net/Dasis/article/details/121663794

(1)赋值

当我们对智能指针进行赋值时,如 ptest2 = ptest,ptest2会接管ptest原来的内存管理权,ptest会变为空指针,如果ptest2原来不为空,则它会释放原来的资源

(2)数组传递值,本质也是移动拷贝

void foo_ary()
{std::vector<std::auto_ptr<int>> Ary;std::auto_ptr<int> p(new int(3));//push_back时不允许如此构造对象Ary.push_back(p);printf("%d\r\n", *p);
}

4.shared_ptr

多个 shared_ptr 智能指针可以共同使用同一块堆内存。并且,由于该类型智能指针在实现上采用的是引用计数机制,即便有一个 shared_ptr 指针放弃了堆内存的“使用权”(引用计数减 1),也不会影响其他指向同一堆内存的 shared_ptr 指针(只有引用计数为 0 时,堆内存才会被自动释放)。

(1)创建

std::shared_ptr<int> p3(new int(10));
std::shared_ptr<int> p5 = std::make_shared<int>(10);
//调用拷贝构造函数
std::shared_ptr<int> p4(p3);//或者 std::shared_ptr<int> p4 = p3;
//调用移动构造函数
std::shared_ptr<int> p5(std::move(p4)); //或者 std::shared_ptr<int> p5 = std::move(p4);

(2) 源码

//
// Created by xuboluo on 2022/9/5.
// shared_prt_demo#include <iostream>
template <typename T>
class my_shared{int count_;T* ptr_;public:// 创建构造函数// 1. 默认构造函数my_shared():count_(0),ptr_(nullptr){}// 2. 传入的是对象my_shared(T* ptr):ptr_(ptr),count_(1){}// 3.传入的是智能指针my_shared(const my_shared<T>& other):count_((other.count_+1)),ptr_(other.ptr_){}// 析构函数~my_shared(){count_--;if(ptr_&&count_==0){delete ptr_;}}// operator = 的方法my_shared* operator=(const my_shared<T>& other){if(this==&other) return this;other.count_++;// 将 prt2 指向的对象给 ptr1 ,并将自己原先的进行释放if(this->ptr_&&0==--this->count_){delete ptr_;}// 释放完之后再向 ptr 赋值this->ptr_ = other.ptr_;this->count_ = other.count_;return this;}// use_countint use_count(){return count_;}
};
int main(){int* p = new int(3);my_shared<int> ptr(new int(3)); // 传入一个对象的指针my_shared<int> ptr2(ptr); // 传入一个智能指针my_shared<int> ptr3 = ptr2;std::cout<<ptr3.use_count();
}

(3)Shared_ptr 的循环引用
如果相互引用 shared_ptr 会造成程序死锁,最终谁也不释放资源
Demo

5.weak_ptr

解决 shared_ptr 相互引⽤时,两个指针的引⽤计数永远不会下降为0,从⽽导致死锁问题。⽽ weak_ptr 是对对象的⼀种弱引⽤,可以绑定到 shared_ptr ,但不会增加对象的引⽤计数。

如何判断 weak_ptr 失效:1.expired():检查被引用的对象是否已删除。2.lock()会返回shared指针,判断该指针是否为空。3.use_count()也可以得到shared引用的个数,但速度较慢

(1)创建

std::shared_ptr<int> sp (new int);
std::weak_ptr<int> wp3 (sp);

(2)如何使用

#include <iostream>
#include <memory>
using namespace std;int main()
{std::shared_ptr<int> sp1(new int(10));std::shared_ptr<int> sp2(sp1);std::weak_ptr<int> wp(sp2);//输出和 wp 同指向的 shared_ptr 类型指针的数量cout << wp.use_count() << endl; // 2//释放 sp2sp2.reset();cout << wp.use_count() << endl; // 1 //借助 lock() 函数,返回一个和 wp 同指向的 shared_ptr 类型指针,获取其存储的数据cout << *(wp.lock()) << endl; // 10return 0;
}

6.unique_ptr

是作用域指针,当超出作用域时就会被销毁然后调用 delete。同⼀时间只能有⼀个智能指针可以指向该对象,每个 unique_ptr 指针指向的堆内存空间的引用计数,都只能为 1,一旦该 unique_ptr 指针放弃对所指堆内存空间的所有权,则该空间会被立即释放回收,而且 unique_ptr 的拷贝构造函数和 operator= 都被 delete 了

(1)创建

std::unique_ptr<int> p4(new int);
std::unique_ptr<int> p5(p4);//错误,堆内存不共享
std::unique_ptr<int> p5(std::move(p4));//正确,调用移动构造函数

(2)如何使用

#include <iostream>
#include <memory>
using namespace std;int main()
{std::unique_ptr<int> p5(new int);*p5 = 10;// p 接收 p5 释放的堆内存int * p = p5.release();cout << *p << endl; // 10//判断 p5 是否为空指针if (p5) {cout << "p5 is not nullptr" << endl;}else {cout << "p5 is nullptr" << endl; // null }std::unique_ptr<int> p6;//p6 获取 p 的所有权p6.reset(p);cout << *p6 << endl; // 10return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/765637.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

用Compute Shader处理图像数据后在安卓机上不能正常显示渲染纹理

1&#xff09;用Compute Shader处理图像数据后在安卓机上不能正常显示渲染纹理 2&#xff09;折叠屏适配问题 3&#xff09;Prefab对DLL中脚本的引用丢失 4&#xff09;如何优化Unity VolumeManager中的ReplaceData 这是第378篇UWA技术知识分享的推送&#xff0c;精选了UWA社区…

css的box-shadow详解

CSS的box-shadow属性用于在元素框上添加阴影效果。它可以为元素提供外阴影或内阴影&#xff0c;并且可以控制阴影的颜色、偏移距离、模糊半径以及扩展半径。 box-shadow属性的基本语法如下&#xff1a; box-shadow: h-shadow v-shadow blur spread color inset;下面是各个参数…

超快的 AI 实时语音转文字,比 OpenAI 的 Whisper 快4倍 -- 开源项目 Faster Whisper

faster-whisper 这个项目是基于 OpenAI whisper 的模型&#xff0c;在上面的一个重写。 使用的是 CTranslate2 的这样的一个库&#xff0c;CTranslate2 是用于 Transformer 模型的一个快速推理引擎。 在相同精度的情况下&#xff0c;faster-whisper 的速度比 OpenAI whisper …

web开发必备之跨域

1.什么是跨域&#xff1f; 当一个请求url的协议、域名、端口三者之间任意一个与当前页面url不同即为跨域 举个例子或许比较生动 当前所在页面请求的页面是否同域原因https://www.csdn.net/https://blog.csdn.net/weixin_56703682√同源&#xff08;同域名同协议同端口&#x…

【网站项目】294火车票订票系统

&#x1f64a;作者简介&#xff1a;拥有多年开发工作经验&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的项目或者毕业设计。 代码可以私聊博主获取。&#x1f339;赠送计算机毕业设计600个选题excel文件&#xff0c;帮助大学选题。赠送开题报告模板&#xff…

EI Scopus双检索| 2024年智能交通与未来出行国际会议(CSTFM 2024)

会议简介 Brief Introduction 2024年智能交通与未来出行国际会议(CSTFM 2024) 会议时间&#xff1a;2024年10月18日-20日 召开地点&#xff1a;中国杭州 大会官网&#xff1a;CSTFM 2024-2024 International Conference on Smart Transportation and Future Mobility(CSTFM 202…

解决修改数据后,前端页面不显示问题

如图&#xff0c;修改数据后&#xff0c;在前端页面不显示的问题&#xff0c;可能是因为缓存问题 解决方案 以为Edge浏览器为例 打开设置左边栏点击隐私&#xff0c;搜索和服务选择清除 Internet Explorer 的浏览数据点击删除&#xff0c;重新启动前端界面即可。

大数据专家3个月自学计划

本人有6年Java开发经验&#xff0c;目前在岗中&#xff0c;之前通过视频教学自学过Hadoop生态技术、flume、kafka、Redis、hive、spark、flink、sqoop、azkaban、ozie、habse、presto、kylin等大数据相关技术&#xff0c;希望利用3个月时间复习&#xff0c;成为大数据专家。以下…

3.18作业

一、网络属性&#xff08;getsockopt、setsockopt&#xff09; 1> 由于在网络通信过程中&#xff0c;套接字是服务于各个层的&#xff0c;但是&#xff0c;每一层中对套接字选项都有一定的权限控制&#xff0c;例如&#xff0c;应用层中对端口号快速重用的限制 2> 如何…

日志收集监控告警平台的选型思考

目前市面上比较常见的日志收集系统有&#xff1a;ELK&#xff0c;Grafana Loki&#xff0c;OpenObserve&#xff0c;SigNoz&#xff0c;Graylog &#xff0c;Syslog-ng&#xff0c;Highlight&#xff0c;接下来我会对这几个一一做分析。 1. ELK ELK 是 Elasticsearch、Logsta…

Linux系统及操作 (10)

Linux系统及操作 (09) [ ping ] [ ping -c ]指定数量 [ ping -c5 192.168.88.2 ] 指定五次交互 DNS服务器 Domain Name System 域名系统 用于实现域名和IP地址相互映射的一个分布式数据库 将域名翻译成可由计算机识别的IP地址,方便用户间的互相访问 计算机无法直接识别**[…

vue2 自定义 v-model (model选项的使用)

效果预览 model 选项的语法 每个组件上只能有一个 v-model。v-model 默认会占用名为 value 的 prop 和名为 input 的事件&#xff0c;即 model 选项的默认值为 model: {prop: "value",event: "input",},通过修改 model 选项&#xff0c;即可自定义v-model …

php 各种魔术函数的触发条件

2024.3.20 1、__construct() __construct() 用于在创建对象时自动触发 当使用 new 关键字实例化一个类时&#xff0c;会自动调用该类的 __construct() 方法 <?php class MyClass {public function __construct() {echo "已触发 __construct 一次";} }$obj new …

js实现旋转矩形,圆形交集并集差集运算并使用canvas展示

region 使用0代表空 1代表有 复制到codepen执行 // 创建三个 Canvas 元素 const intersectionCanvas document.createElement(canvas); const unionCanvas document.createElement(canvas); const differenceCanvas document.createElement(canvas);intersectionCanvas.wid…

Springboot集成Rabbitmq

Springboot集成Rabbitmq实现请求异步处理 一、Docker部署rabbitmq 1. docker pull rabbitmq:3.7.8rabbitmq为需要拉取的镜像名称&#xff0c;3.7.8为版本号 2. docker run -d -p 5672:5672 -p 15672:15672 --name rabbitmq rabbitmq:3.7.8运行拉取到的镜像文件&#xff1b;-d…

本人用编译

板子方 修改ip&#xff08;保证板子和主机在同一个网段&#xff09; mount -t nfs -o rw,nolock,nfsvers3 192.168.1.200:/home/violet/nfs get/ 互通的文件在~目录下get文件内 电脑方 使用arm-linux-gnueabihf-gcc 编译

外部提供控制程序

外部提供控制程序 文件编号&#xff1a;XXX 1、目的和适用范围 规范在研发与生产过程中所涉及到的采购、外包行为方式&#xff0c;对外部提供过程和产品进行控制&#xff0c;评估、选择及控制外部提供方&#xff0c;并对采购活动及外包过程进行有效地控制&#xff0c;确保外部…

性能优化(CPU优化技术)ARM Neon 详解

原文来自ARM neon详解 &#x1f3ac;个人简介&#xff1a;一个全栈工程师的升级之路&#xff01; &#x1f4cb;个人专栏&#xff1a;高性能&#xff08;HPC&#xff09;开发基础教程 &#x1f380;CSDN主页 发狂的小花 &#x1f304;人生秘诀&#xff1a;学习的本质就是极致重…

AI新工具(20240322) 免费试用Gemini Pro 1.5;先进的AI软件工程师Devika;人形机器人Apptronik给你打果汁

✨ 1: Gemini Pro 1.5 免费试用Gemini Pro 1.5 Gemini 1.5 Pro是Gemini系列模型的最新版本&#xff0c;是一种计算高效的多模态混合专家&#xff08;MoE&#xff09;模型。它能够从数百万个上下文Token中提取和推理细粒度信息&#xff0c;包括多个长文档和数小时的视频、音频…

ASP.NET控件

目录 TextBox 控件 Button 控件 HyperLink 控件 CheckBox 控件 RadioButton 控件 ListBox 控件 DropDownList 控件 Repeater 控件 DataList 控件 GridView 控件 RequiredFieldValidator 控件 RangeValidator 控件 CompareValidator 控件 RegularExpressionValidat…