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

锦江区建设和交通局网站绵阳城乡住房建设厅网站

锦江区建设和交通局网站,绵阳城乡住房建设厅网站,东南亚购物网站排名,做ppt哪个网站好目录一、理解智能指针1.普通指针的使用二、智能指针1.auto_ptr2.unique_ptr3.shared_ptr#xff08;1#xff09;了解shared_ptr#xff08;2#xff09;shared_ptr的缺陷4.weak_ptr本文代码在win10的vs2019中通过编译。 一、理解智能指针 1.普通指针的使用 如果程序需要… 目录一、理解智能指针1.普通指针的使用二、智能指针1.auto_ptr2.unique_ptr3.shared_ptr1了解shared_ptr2shared_ptr的缺陷4.weak_ptr本文代码在win10的vs2019中通过编译。 一、理解智能指针 1.普通指针的使用 如果程序需要动态申请内存空间我们通常使用malloc或者new从堆上申请空间从堆上申请的空间是需要释放的否则就会造成内存泄漏。 不同的申请方式也对应着不同的释放方式malloc申请的空间通过free释放new申请的空间通过delete释放。 正常来讲如果我们从堆上申请了空间那么在空间使用完毕后就需要将空间释放但是如果程序在运行时出错直接崩溃那么我们的空间就来不及释放从而造成资源泄露。 下面这段代码因为试图对空指针解引用因此会崩溃所以ptr指向的空间就没有释放造成资源泄露 #define _CRT_SECURE_NO_WARNINGS #include iostream using namespace std;int main() { int* ptr new int;//ptr指针申请了空间int* pn nullptr;//pn指针指向空cout *pn;//对空指针解引用造成崩溃delete ptr;//释放ptr申请的空间因为程序崩溃无法运行到这里 }因此如果要避免这种情况就需要在所有可能会中途退出的位置之前释放资源或者是使用异常来解决。但这样的解决办法会让代码变得复杂、庞大。 因此我们需要一种智能的指针让指针使用完毕后自动释放申请的空间也就是智能指针。 我们可以自己来实现一个简单的智能指针当然会有很多缺陷但主要是了解一下思想。想一想类的构造函数和析构函数生成一个类的对象时调用构造方法销毁类的对象时调用析构方法。因此我们可以在构造函数中传入空间地址在析构函数中释放资源这样就可以把一个类的对象当指针一样使用了。 看看下面这段代码 #define _CRT_SECURE_NO_WARNINGS #include iostream using namespace std;templatetypename T class SmartPtr { public:T* ptr;//指针 public:SmartPtr(T* _p nullptr):ptr(_p){}~SmartPtr() {if (ptr ! nullptr) {delete ptr;//释放空间}}T operator*() {return *ptr;}T* operator-() {return ptr;} };struct Num {int a;int b; };void Test() {//new会从堆上申请空间并返回空间首地址将空间首地址作为参数传递SmartPtrint s1(new int);*s1 10;//通过重载的*运算符修改空间中的值SmartPtrNum s2(new Num);s2-a 11;//通过-运算符直接访问结构体对象的成员变量s2-b 12; }int main() {Test();_CrtDumpMemoryLeaks();//检测内存泄漏 }但是这个简单版本的智能指针有一个很大的缺点浅拷贝。编译器生成的默认拷贝构造函数和赋值运算符重载都是浅拷贝如果通过拷贝构造和赋值运算符重载来给其他对象赋值当对象生命周期结束调用析构函数的时候就会因为多次释放同一个资源造成程序崩溃。 但是不能因为要解决浅拷贝的问腿就自己定义深拷贝的拷贝构造函数和赋值运算符重载因为智能指针是把对象当指针一样使用指针只负责管理资源。如果我们进行深拷贝那么多个对象就不能使用同一份资源了。 二、智能指针 为了解决浅拷贝的问腿来介绍C中的智能指针这里介绍四种auto_ptr不推荐使用仅作了解、unique_ptr直接禁止拷贝、shared_ptr、weak_ptr。 1.auto_ptr 解决浅拷贝的方式资源转移如果要用b给a赋值或者是拷贝构造就直接把b的资源转移给a然后让b指向空。所以b就不能使用这个资源了 #define _CRT_SECURE_NO_WARNINGS #include iostream #include memory using namespace std;void Test() {auto_ptrint ap1(new int);*ap1 10;auto_ptrint ap2(ap1);//用ap1拷贝构造ap2*ap2 12; }int main() {Test();_CrtDumpMemoryLeaks();//检测内存泄漏 }来看看auto_ptr的缺陷如图所示用ap1拷贝构造ap2后ap1的指针就置为空了因为资源从ap1转移给ap2了ap1以后就不能使用这个资源了。因此不推荐使用不然很可能在不知情的情况下就去对ap1解引用了。 2.unique_ptr 解决浅拷贝的方式禁止拷贝只要不能拷贝就不会有浅拷贝发生。从根源解决问题 如果确定这个资源只会被一个指针管理就使用unique_ptr。 #define _CRT_SECURE_NO_WARNINGS #include iostream #include memory using namespace std;void Test() {unique_ptrint up1(new int);*up1 10;//unique_ptrint up2(up1); 用up1拷贝构造up2会报错//unique_ptrint up3 up1; 用up1给up2赋值会报错 }int main() {Test();_CrtDumpMemoryLeaks();//检测内存泄漏 }3.shared_ptr 1了解shared_ptr 解决浅拷贝的方式引用计数。通过计数来判断当前有多少个shared_ptr指向了这个被管理的资源当计数变成0说明此时没有指针管理这个资源因此可以释放这个资源。 #define _CRT_SECURE_NO_WARNINGS #include iostream #include memory using namespace std;void Test() {shared_ptrint sp1(new int);*sp1 10;shared_ptrint sp2(sp1);*sp2 11;*sp1 12;cout sp1管理的资源同时被 sp1.use_count() 个智能指针管理 endl; }int main() {Test();_CrtDumpMemoryLeaks();//检测内存泄漏 }如图所示sp1和sp2同时管理资源资源的地址是一样的说明两个指针管理的是同一个资源。 shared_ptr中有两个变量一个变量ptr指向资源的空间首地址另一个变量pcount指向引用计数的空间。引用计数空间的值初始状态是1每当有一个智能指针管理了这个资源就会将这个资源对应的引用计数加1每当有一个智能指针不再管理这个资源就会把引用计数减1当引用计数变成0说明已经没有指针管理这个资源因此就可以释放这个资源了。 2shared_ptr的缺陷 shared_ptr有一个很大的缺陷循环引用。 如下代码定义了链表结点结构体 struct ListNode该结构体包含了三个成员变量value用来保存该结点的值next用来指向下一个链表结点prev用来指向前一个链表结点。next和prev都是shared_ptr类型的智能指针变量。 在函数Testshared()中使用智能指针shared_ptr管理ListNode对象然后更新它们的指针指向让两个链表结点连接起来。 这份代码运行完毕以后会造成资源泄露。 #define _CRT_SECURE_NO_WARNINGS #include iostream #include memory using namespace std;struct ListNode { public:shared_ptrListNode next;//next指向下一个链表结点shared_ptrListNode prev;//prev指向前一个链表结点int value; public:ListNode(const int data0) :next(nullptr),prev(nullptr),value(data){}~ListNode() {cout 析构函数 endl;} };void Testshared() {shared_ptrListNode sp1(new ListNode(4));shared_ptrListNode sp2(new ListNode(5));sp1-next sp2;sp2-prev sp1; }int main() {Testshared();_CrtDumpMemoryLeaks();//检测内存泄漏 }来看看为什么会造成资源泄露。 下图是sp1和sp2刚构建好的样子智能指针内部的ptr指针指向链表结点资源的首地址pcount指针指向存储引用计数的空间。 刚创建出来sp1和sp2时由于每个链表结点都只被一个智能指针管理因此引用计数都是1。 下图是 sp1-next sp2; sp2-prev sp1; 执行后的情况因为ListNode结构体内部的next和prev是用shared_ptr实现的因此next和prev也具有指针ptr和引用计数pcount。 由于ListNode2被ListNode1的next指向也就代表着多了一个指针管理ListNode2因此ListNode2的引用计数需要加1。 ListNode1被ListNode2的prev指向代表着多了一个指针管理ListNode1因此ListNode1的引用计数需要加1。 当Testshared函数执行完毕作为局部对象的sp1和sp2就需要被销毁后创建的先销毁因此首先销毁sp2。 sp2的ptr与ListNode2断开连接然后会将引用计数空间的值减1引用计数变成1代表还有1个指针在管理ListNode2因此不能释放ListNode2的资源。 然后销毁sp1sp1同样先断开与ListNode1的联系然后将引用计数空间的值减1引用计数变成1代表还有1个指针在管理ListNode1因此不能释放ListNode1的资源。 然后现在就尴尬了如果要释放ListNode1就要先把ListNode1的引用计数置为0因此需要让ListNode2的prev不要指向ListNode1而ListNode2的prev是ListNode2的成员变量因此就必须要释放ListNode2才能让prev断开与ListNode1的联系。 但是要释放ListNode2就需要把ListNode2的引用计数置为0 …… 这样就成套娃了因此直到最后也没有释放资源析构函数没有调用造成了内存泄漏。 如下图 4.weak_ptr weak_ptr无法单独管理资源。 weak_ptr就是用来解决shared_ptr的循环引用的将weak_ptr和shared_ptr搭配使用就可以解决循环引用的问题。 在上面介绍shared_ptr的时候为了方便理解因此直接说的是引用计数。实际上shared_ptr的引用计数有两个_Uses 和 _Weaks。两个值初始值都是1 一个资源每当被一个shared_ptr智能指针管理那么_Uses加1。一个资源每当被weak_ptr智能指针管理_Weaks加1。 因此_Uses 和 _Weaks就表示了这个资源被多少个weak_ptr智能指针或者多少个shared_ptr智能指针管理。 当引用计数空间的 _Uses 变成0说明被管理的资源可以释放了。当_Uses 和 _Weaks都变成0说明引用计数空间可以被释放了。 将前一段代码进行改造将next和prev改为weak_ptr智能指针同时要去掉构造函数中的相关内容。因为weak_ptr不能单独管理资源就连空指针都不允许。 #define _CRT_SECURE_NO_WARNINGS #include iostream #include memory using namespace std;struct ListNode { public:weak_ptrListNode next;//next指向下一个链表结点weak_ptrListNode prev;//prev指向前一个链表结点int value; public:ListNode(const int data 0): value(data){}~ListNode() {cout 析构函数 endl;} };void Testshared() {shared_ptrListNode sp1(new ListNode(4));shared_ptrListNode sp2(new ListNode(5));sp1-next sp2;sp2-prev sp1; }int main() {Testshared();_CrtDumpMemoryLeaks();//检测内存泄漏 }通过图片来理解改造后的代码下图是刚创建出来sp1和sp2的情况。sp2和sp1指向的引用计数空间中有两个值_Uses 和 _Weaks。初始状态都是1 当 sp1-next sp2; sp2-prev sp1; 运行后ListNode1的next指向了ListNode2ListNode2的prev指向了ListNode1。 ListNode1的next指向ListNode2因此next中的_Ptr指向ListNode2的空间首地址_Rep指向ListNode2的引用计数空间。另一方同理。 因为next和prev是weak_ptr智能指针因此两方的引用计数空间的_Weaks都要加1_Weaks变成2。 如图 当Testshared函数执行完毕作为局部变量的sp1和sp2就要被销毁后创建的先销毁因此先销毁sp2。 首先断开sp2的_Ptr和ListNode2的联系因此该链表结点对应的引用计数空间的_Uses要减1_Uses变成0说明可以释放ListNode2了因此需要把ListNode2的prev与ListNode1断开联系因此ListNode1对应的引用计数空间的_Weaks需要减1_Weaks变成1。 把ListNode2的资源处理干净后就需要把ListNode2对应的引用计数空间的_Weaks减1然后sp2就可以释放了。ListNode2对应的引用计数空间的_Weaks变成1说明该链表结点对应的引用计数空间还不能释放。   释放了sp2后就需要释放sp1了首先断开sp1的_Ptr和LsitNode1的联系这样该链表结点对应的引用计数空间的_Uses就需要减1_Uses变成0说明ListNode1的资源可以释放了这样就需要断开next和其他结点的联系然后ListNode2对应的引用计数空间的_Weaks就需要减1_Weaks变成0说明引用计数空间可以释放了。 ListNode1的资源处理后ListNode1对应的引用计数空间中的_Weaks就需要减1然后_Weaks变成0说明这个引用计数空间可以被释放了。 析构函数此时也被正常调用了shared_ptr的循环引用被解决了。
http://www.hkea.cn/news/14419853/

相关文章:

  • 个人建站模板网站图片特效源码
  • 基于wordpress的英文小游戏站外贸网站开发
  • 怎样用ps做网站首页图片如何搭建一个论坛网站
  • 高端网络建站jpress 和wordpress
  • 网站字号网络服务器租赁费一般多少钱
  • 建设银行网站注册用户名不通过“网站制作”
  • 新浪网站是什么程序做的网站服务器租用一般费用
  • 怎样做才能让网站帮忙送东西wordpress 系统环境
  • 丹东网站建设公司wordpress文章伪静态
  • 长沙房地产信息网官网seo如何优化排名
  • 499可以做网站外贸网站设计公司
  • 一个网站可以做多少个小程序centos 安装 wordpress
  • 电子商务网站的开发原则包括那些网站能够做推广
  • 潍坊正规网站建设公司南昌市房产网
  • 什么是网站二级目录提高网站关键词排名
  • 山东潍坊网站制作公司安的网络网站建设
  • 广州11个区排名外贸网站建设网站优化
  • 海淀网站建设联系方式制作一个网页游戏需要多少钱
  • 进网站后台显示空白如何在易语言上做网站
  • 重庆做木门网站公司简介开源网站后台管理系统
  • 设计品牌网站公司制作宣传片视频
  • 网站大全免费下载国家开发银行助学贷款网站
  • 网站开发制作价格wordpress引用js代码
  • 网站优化排名方案想做个网站都需要什么
  • 做系统软件的网站win2003搭建wordpress
  • 网站备案和服务器备案吗iis 如何新建网站
  • dw网站结构图怎么做中国企业500强营收总额首超百万亿
  • asp.net网站打不开html页面天华集团设计公司
  • 深圳商城网站开发免费建立手机网站
  • 柳州市建设工程质量安全监督管理处网站塘厦医院