网站维护公司哈尔滨网页制作课程

web/2025/9/30 1:43:25/文章来源:
网站维护公司哈尔滨,网页制作课程,故事式的软文广告例子,wap手机网站源码前言#xff1a;在此之前我们已经学习到了异常的使用#xff0c;虽然异常在大部分情况都还可以#xff0c;但也存在太多缺陷#xff0c;对于异常的问题#xff0c;入内存泄漏#xff0c;在复杂的场景下使用起来也是非常麻烦。为了更好的解决这些问题#xff0c;c11中引入…前言在此之前我们已经学习到了异常的使用虽然异常在大部分情况都还可以但也存在太多缺陷对于异常的问题入内存泄漏在复杂的场景下使用起来也是非常麻烦。为了更好的解决这些问题c11中引入了智能指针。 目录 一什么是智能指针 二智能指针的使用 简化autoptr 简化uniqueptr 简化sharedptr 简化weakptr 定制删除器 一什么是智能指针 智能指针RAII是一种C标准库提供的对象用于管理动态分配的内存用对象生命后期来控制程序资源。智能指针本身是一个类对象它封装了指向动态分配的内存的指针并提供了自动释放内存的机制。智能指针的行为类似于常规指针可以通过解引用操作符*和成员访问操作符-来访问内存中的数据。C11引入了3个智能指针类型 std::unique_ptrT独占资源所有权的指针。 std::shared_ptrT共享资源所有权的指针。 std::weak_ptrT共享资源的观察者需要和std::shared_ptr一起使用不影响资源的生命周期。 二智能指针的使用 我们还是先给一个例子这里就是空间得不到释放。 //还是以分母不能为零为例 double Division(int x, int y) {if (y 0){throw invalid_argument(除零错误);//这里我们是直接使用库里异常(无效参数)}else{return double(x) / double(y);} }//如果不采用异常的重新抛出如何释放这里的arr void Func() {int* arr new int[10];int x; int y;cin x y;Division(x, y);delete []arr;arr nullptr;cout reliszed delete arr endl; } int main() {try{Func();}catch (exception e){cout e.what();}return 0; } 解决办法我们封装一个指针将我们的这个需要释放的指针给这个只针对想只针对象在跳出生命周期后会自动调用析构函数来释放这里的空间。 而这里就是RAII----通过控制对象的生命周期来控制资源的释放 templateclass Tclass Smartptr { public:Smartptr(T *ptr):_ptr(ptr){}~Smartptr(){delete []_ptr;cout delete ptr endl;} private:T* _ptr; }; //还是以分母不能为零为例 double Division(int x, int y) {if (y 0){throw invalid_argument(除零错误);//这里我们是直接使用库里异常(无效参数)}else{return double(x) / double(y);} }//如果不采用异常的重新抛出如何释放这里的arr void Func() {int* arr new int[10];int x; int y;cin x y;//在此之前使用一个指针对象来控制我的生命后期//无异常正常使用有异常生命周期结束释放空间Smartptrint p(arr);Division(x, y);/*delete []arr;arr nullptr;cout reliszed delete arr endl;*/ } int main() {try{Func();}catch (exception e){cout e.what();}return 0; } 但是智能指针并不是这么简单就完了我们的目的是要把它当作指针一样使用。因此整体我们还要实现他的一些接口。 templateclass Tclass Smartptr { public:Smartptr(T* ptr) :_ptr(ptr){}~Smartptr(){delete _ptr;cout delete ptr endl;}//使它想指针一样使用T operator*(){return *_ptr;}T* operator-(){return _ptr;} private:T* _ptr; }; 但此时的智能指针还存在问题首先就是赋值浅拷贝会释放两次我们可能会想到再写一个拷贝构造不经行了吗事实上这里使用深拷贝是解决不掉问题的。 这里的内存问题不同于之前的容器比如vector我们实例化一个对象并初始化内容系统就为对象分配该空间并初始化拷贝给另一个对象系统会为该对象分配资源并初始化。即他们的空间与资源是不一样的但是对于智能指针我们就是管理这一部分资源无论拷贝给谁谁管理这一部分资源深拷贝的话那我拷贝几次有几份该资源这并不属于(RAII)我们使用智能指针的理念。 那么如何解决这样的问题这里我们就使用 引用计数的方法来进行拷贝与释放。 再此之前根据c的发展也是不断提出更新新的方案 简化autoptr templateclass Tclass Autoptr { public:Autoptr(T* ptr) :_ptr(ptr){}~Autoptr(){delete _ptr;cout delete ptr endl;_ptr nullptr;}//通过管理权转移的方式实现拷贝// 把我拷贝给你Autoptr(AutoptrT p):_ptr(p._ptr){//通过把我置空将资源转移给你p._ptr nullptr;}//使它想指针一样使用T operator*(){return *_ptr;}T* operator-(){return _ptr;}private:T* _ptr; }; autoptr的原理很简单给谁拷贝就把权限给谁原本资源的位置再把自己置空实现资源转移但这种写法显而易见的就是空指针的访问若有人不熟悉这个指针的原理去访问拷贝后的原指针就会导致对象悬空。 使用autoptr使得很多人被坑之后出现第二个版本 简化uniqueptr uniqueptr的做法比较绝既然拷贝有问题那干脆不支持你拷贝赋值了通过私有只申明不实现的方法使我们无法访问拷贝构造。 templateclass Tclass Uniqueptr { public:Uniqueptr(T* ptr) :_ptr(ptr){}~Uniqueptr(){delete _ptr;cout delete ptr endl;_ptr nullptr;}//T operator*(){return *_ptr;}T* operator-(){return _ptr;}//c11做法/*Uniquetptr(UniquetptrT p) delete;UniquetptrT operator(UniquetptrT p) - delete;*/ private://只申明不实现 c98做法Uniqueptr(UniqueptrT p);//拷贝构造UniqueptrT operator(UniqueptrT p);//赋值T* _ptr; }; 但是不能拷贝不能解决根本问题总有要拷贝的情况因此又出来第三代智能指针。 简化sharedptr sharedptr就是金泰主要认识的智能指针通过引用技术的方式实现赋值。 在实现的时候我们增加一个参数count,count再调用构造函数时会被初始化为1在拷贝的时候此时这里的_ptr与原来的指向同一空间这里的count也与原来的count指向同一空间且对于拷贝给的这个count再调用析构时对应的count只有一份count先--,若count0说明到达释放的条件。就实现了资源的转移。 但是对于赋值是分两种情况的一种是同类资源的赋值。 一种是一类资源的赋值。 templateclass Tclass Sharedptr { public:Sharedptr(T* ptr) :_ptr(ptr),count(new int (1)){}~Sharedptr(){(*count)--;release();}void release(){if ((*count) 0){delete _ptr;delete count;cout finish released endl;_ptr nullptr;count nullptr;}}Sharedptr(const Sharedptr ptr):_ptr(ptr._ptr),count(ptr.count){(*ptr.count);//拷贝的时候次数加加}//重载赋值 thisptrSharedptrT operator(const Sharedptr ptr){//赋值的时候表示 把我这份资源交给你,你的资源被覆盖掉//判断不是自身赋值if (ptr.count ! this-count){//左边赋值给右边 因此右边被覆盖掉 先count--代表右边已经被析构一次*(this-count)--;//判断此时为空不if (*(ptr.count) 0){release();}//不为空就进行覆盖this-count ptr.count;this-_ptr ptr._ptr;//覆盖后此时的ptr指向 左边的资源//因此左边的count*(this-count);}return *this;}T operator*(){return *_ptr;}T* operator-(){return _ptr;}private:T* _ptr;int* count; }; 计数是几就代表此时有多少个对象指向这里的资源。 此时的sharedptr已经基本实现我们的期望了但在使用中又发现了一个无法解决的问题循环引用。循环引用会导致死循环。 struct ListNode {ListNode(){cout 调用构造 endl;}~ListNode(){cout 调用析构 endl;}int data;SharedptrListNode next;SharedptrListNode prev; }; void test_sharedptr1() {//假设害怕这里的节点得不到释放我们用sharedptr来管理SharedptrListNode p1 new ListNode();SharedptrListNode p2 new ListNode();p1-next p2;p2-prev p1;} int main() {test_sharedptr1();return 0; }我们模拟一个双链表的节点的链接此时运行这个程序就会崩掉但是删除其中一个的链接调用就会成功这里主要原因就是析构死循环了。 若是有一次链接 若是如上代码的两次链接 即先释放两个对象此时都为1在释放两个其中的节点而释放其中的一个节点是被牵制的需要我们再次看 上一个牵制的。如此往上就形成了一个死循环导致资源没有被释放。 库里加了explicet就不可以通过转换构造函数实现隐式类型转换的发生。 简化weakptr 为了专门解决也这个问题再sharedptr的基础修改引入了weakptr。这里的weakptr已经不属于RAII了,这里的已经不是智能指针了使用weakptr,在这个地方不会引用计数。 templateclass Tclass Sharedptr { public:Sharedptr():_ptr(nullptr), count(new int(1)){}Sharedptr(T* ptr) :_ptr(ptr),count(new int (1)){}~Sharedptr(){(*count)--;release();}void release(){if ((*count) 0){delete _ptr;delete count;//cout finish released endl;_ptr nullptr;count nullptr;}}Sharedptr(const Sharedptr ptr):_ptr(ptr._ptr),count(ptr.count){(*ptr.count);//拷贝的时候次数加加}//重载赋值 thisptrSharedptrT operator(const Sharedptr ptr){//赋值的时候表示 把我这份资源交给你,你的资源被覆盖掉//判断不是自身赋值if (ptr.count ! this-count){//左边赋值给右边 因此右边被覆盖掉 先count--代表右边已经被析构一次*(this-count)--;//判断此时为空不if (*(ptr.count) 0){release();}//不为空就进行覆盖this-count ptr.count;this-_ptr ptr._ptr;//覆盖后此时的ptr指向 左边的资源//因此左边的count*(this-count);}return *this;}T operator*(){return *_ptr;}T* operator-(){return _ptr;}int use_count()const{return *count;}T* get()const{return _ptr;} private:T* _ptr;int* count; };templateclass Tclass Weakptr { public://weakptr就不参与计数Weakptr() :_ptr(nullptr){}Weakptr(const SharedptrT p):_ptr(p.get()){}Weakptr operator(const SharedptrT p){_ptr p.get();return *this;}T operator*(){return *_ptr;}T* operator-(){return _ptr;}private:T* _ptr; };定制删除器 上述的我们都是针对单一的指针若是指针数组释放就不会正确释放程序是崩溃的为了使我们的释放要考虑周全因此这里释放我们可以使用仿函数lambda或者函数指针进行删除。 由于库中的删除器实在构造里调用的因此我们在实现时通过在构造传参增加一个包装器来初始化之后析构的时候调用包装器并在默认情况下给缺省值。 templateclass Tclass Sharedptr {public:Sharedptr() :_ptr(nullptr), count(new int(1)){}templateclass DELSharedptr(T* ptr, DEL del) :_ptr(ptr),count(new int (1)), del(del){}~Sharedptr(){(*count)--;release();}void release(){if ((*count) 0){del(_ptr) ;delete count;//cout finish released endl;_ptr nullptr;count nullptr;}}Sharedptr(const Sharedptr ptr):_ptr(ptr._ptr),count(ptr.count){(*ptr.count);//拷贝的时候次数加加}//重载赋值 thisptrSharedptrT operator(const Sharedptr ptr){//赋值的时候表示 把我这份资源交给你,你的资源被覆盖掉//判断不是自身赋值if (ptr.count ! this-count){//左边赋值给右边 因此右边被覆盖掉 先count--代表右边已经被析构一次*(this-count)--;//判断此时为空不if (*(ptr.count) 0){release();}//不为空就进行覆盖this-count ptr.count;this-_ptr ptr._ptr;//覆盖后此时的ptr指向 左边的资源//因此左边的count*(this-count);}return *this;}T operator*(){return *_ptr;}T* operator-(){return _ptr;}int use_count()const{return *count;}T* get()const{return _ptr;} private:T* _ptr;int* count;functionvoid(T*) del [](T* ptr) {delete ptr; }; };

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

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

相关文章

做网站哪些公司苏州首页排名关键词优化

前言 MyBatis框架中使用的5种设计模式分别是:1、建造者模式(生成器模式)。2、工厂模式。3、单例模式。4、代理模式。5、适配器模式。 1、建造者模式(生成器模式) 在MyBatis环境的初始化过程中,SqlSessio…

网站解决方案环球资源网怎么找客户

最近面试过一些人, 发现即使经验丰富的开发人员, 对于一些基础的理论和细节也常常会模糊. 写本文是因为就我自己而言第一次学习下面的内容时发现自己确实有所收获和感悟. 其实我们容易忽视的javascript的细节还有更多, 本文仅是冰山一角. 希望大家都能通过本文有所斩获.一. Jav…

网站通栏代码学校网站源码 带wap手机端

#这个夏天我们一定要去看海# 出国旅行时,语言障碍常常是最让人头疼的问题之一。 特别是在像缅甸这样英语并不普及的国家,基本的日常交流,比如用餐或问路,都可能成为难题。 然而,随着技术的进步,现在有了…

佛山市网站开发个人网站怎么命名

1. 题目 设计一个支持在平均 时间复杂度 O(1) 下,执行以下操作的数据结构。 insert(val):当元素 val 不存在时,向集合中插入该项。 remove(val):元素 val 存在时,从集合中移除该项。 getRandom:随机返回现…

在线音乐播放网站模板郑州网站建设兄长好

java 用流创建流在许多情况下,声明性代码(例如,具有Streams的功能组合)提供了出色的代码指标。 通过该动手实验文章系列进行编码,并成为Java Streams的主教练,从而成为一名更好的Java程序员。 Streams的整…

南京制作网站公司网站正规网站建设推荐谁好呢

类型保护是一种TypeScript技术,用于获取变量类型信息,通常使用在条件块语句中。 类型守卫是返回布尔值的常规函数,接受一个类型并告诉TypeScript是否可以缩小到更具体的类型。 TypeScript类型保护的方式 类型断言 类型断言是一种告诉编译器…

阿里云带宽5m能做什么网站小规模公司需要交哪些税

npm 和 yarn 都是 JavaScript 的包管理工具,用于管理项目中的依赖包。 安装速度 yarn: 速度较快,因为它会缓存已下载的包,并在安装时利用并行下载来最大化资源利用率。 npm: 速度较慢,尤其是在网络不稳定的情况下,可…

电商网站开发需要多少钱网站开发合同官司

java中使用es的dsl我们大多数人已经编写了一些处理图论算法的程序,例如找到两个顶点之间的最短路径,找到给定图的最小生成树等等。 在这些算法的每一种中,表示图形的编程方式是使用邻接矩阵或邻接列表 。 两者都不是定义图形输入的非常直观的…

有口碑的郑州网站建设企业网站托管技巧

目录 1.ChatGPT 是什么 2. ChatGPT 的发展史 3.ChatGPT 优缺点 4.ChatGPT 在未来生活中的发展趋势和应用 5.ChatGPT经历了几个版本 1.ChatGPT 是什么 ChatGPT 是一个在线聊天机器人,可以与使用者进行语义对话和提供帮助。它可以回答各种问题,提供建议…

微信php网站开发流程娄底seo

二叉树第k个大的节点 二叉树文章列表: 数据结构与算法–面试必问AVL树原理及实现 数据结构与算法–二叉树的深度问题 数据结构与算法–二叉堆(最大堆,最小堆)实现及原理 数据结构与算法–二叉查找树转顺序排列双向链表 数据…

深圳附近做个商城网站找哪家公司好wordpress网站上线

P1736 创意吃鱼法 题目描述 回到家中的猫猫把三桶鱼全部转移到了她那长方形大池子中,然后开始思考:到底要以何种方法吃鱼呢(猫猫就是这么可爱,吃鱼也要想好吃法 ^_*)。她发现,把大池子视为01矩阵&#xff0…

想要个免费网站推上网站

目录 一,代理模式和适配器模式区别 二,代理模式 三,特点 四,组成部分和实现步骤 五,案例 六,应用场景 一,代理模式和适配器模式区别 意图:代理模式控制访问并可能添加额外功能…

郑州网站建设维护公司客户网站开发全流程

文章目录 🎍序言🌳加法计算器🚩准备工作🚩约定前后端交互接⼝🌲后端服务器代码的书写 🌴用户登录🚩效果展示🚩准备工作🚩约定前后端交互接⼝🎈需求分析&#…

做网站需要什么图片广州番禺最新通告

谈谈 final、finally、 finalize 有什么不同?final 可以用来修饰类、方法、变量,分别有不同的意义,final 修饰的 class 代表不可以继承扩展,final 的变量是不可以修改的,而 final 的方法也是不可以重写的(o…

黄岩网站开发网站制作的收费

列表滑动性能优化是一个老生常谈的问题,最近在做项目的时候又遇到了列表滑动卡顿的问题,我在经过多次思考和尝试后,终于找到了滑动卡顿的元凶,于是将经验总结下来。ViewHolder先说说最常规的ViewHolder。ViewHolder的出现是为了解…

海南省建设网站的公司深圳网站seo地址

题目 产品数据表: Products 写一段 SQL来查找在 2019-08-16 时全部产品的价格,假设所有产品在修改前的价格都是 10 。 以 任意顺序 返回结果表。 查询结果格式如下例所示。 示例 1: 解题思路 1.题目要求我们查找在 2019-08-16 时全部产品的价格,假设所…

外贸公司访问国外网站网站做优化

问题描述: 农夫John的一头牛逃跑了,他想要将逃跑的牛找回来。现假设农夫John和牛的位置都在一条直线上,农夫John的初始位置为N(0≤N≤100,000),牛的初始位置为K(0≤K≤100,000)。农夫…

网站内链调整专业高端网站设计首选

paramiko模块 介绍: paramiko是一个用于做远程控制的模块,使用该模块可以对远程服务器进行命令或文件操作,值得一说的是,fabric和ansible内部的远程管理就是使用的paramiko来现实。 2. 下载安装 pip3 install paramiko #在pytho…

注册个空壳公司需要多少钱企业网站seo优化公司

GitHub 面对学生推出了学生认证服务,通过认证后就可以得到学生包,学生包大概有十几项优惠,包括 DATADOG Pro 帐户、免费两年的10台服务器,Icons8 3个月的带图标,照片,插图和音乐订阅服务、JETBRAINS 专业桌…

建设监督网站搭建网站的过程

JS文件命名 一般采用的是小驼峰命名法,如 pieChartHelp 第一个单词小写,其他单词首字母大写 Components 文件命名 一般采用的是大驼峰命名法,如PieChart 所有单词的首字母大写 常量命名 一般全部大写,每个单词使用分隔符隔开&…