dedecms网站地图生成谈谈你对网站建设有什么样好的建设意见

张小明 2025/12/31 17:03:57
dedecms网站地图生成,谈谈你对网站建设有什么样好的建设意见,义乌网站建设公司价位,深圳网站设计公司电话智能指针 智能指针的使⽤场景分析 下⾯程序中我们可以看到#xff0c;new了以后#xff0c;我们也delete了#xff0c;但是因为抛异常导#xff0c;后⾯的delete没有得到执⾏#xff0c;所以就内存泄漏了#xff0c;所以我们需要new以后捕获异常#xff0c;捕获到异常…智能指针智能指针的使⽤场景分析下⾯程序中我们可以看到new了以后我们也delete了但是因为抛异常导后⾯的delete没有得到执⾏所以就内存泄漏了所以我们需要new以后捕获异常捕获到异常后delete内存再把异常抛出但是因为new本⾝也可能抛异常连续的两个new和下⾯的Divide都可能会抛异常让我们处理起来很⿇烦。智能指针放到这样的场景⾥⾯就让问题简单多了。double Divide(int a, int b) { // 当b 0时抛出异常 if (b 0) { throw Divide by zero condition!; } else { return (double)a / (double)b; } } void Func() { // 这⾥可以看到如果发⽣除0错误抛出异常另外下⾯的array和array2没有得到释放。 // 所以这⾥捕获异常后并不处理异常异常还是交给外⾯处理这⾥捕获了再重新抛出去。 // 但是如果array2new的时候抛异常呢就还需要套⼀层捕获释放逻辑这⾥更好解决⽅案 // 是智能指针否则代码太戳了 int* array1 new int[10]; int* array2 new int[10]; // 抛异常呢 try { int len, time; cin len time; cout Divide(len, time) endl; } catch (...) { cout delete [] array1 endl; cout delete [] array2 endl; delete[] array1; delete[] array2; throw; // 异常重新抛出捕获到什么抛出什么 } // ... cout delete [] array1 endl; delete[] array1; cout delete [] array2 endl; delete[] array2; } int main() { try { Func(); } catch (const char* errmsg) { cout errmsg endl; } catch (const exception e) { cout e.what() endl; } catch (...) { cout 未知异常 endl; } return 0; }RAII和智能指针的设计思路• RAII是Resource Acquisition Is Initialization的缩写他是⼀种管理资源的类的设计思想本质是⼀种利⽤对象⽣命周期来管理获取到的动态资源避免资源泄漏这⾥的资源可以是内存、⽂件指针、⽹络连接、互斥锁等等。RAII在获取资源时把资源委托给⼀个对象接着控制对资源的访问资源在对象的⽣命周期内始终保持有效最后在对象析构的时候释放资源这样保障了资源的正常释放避免资源泄漏问题。智能指针类除了满⾜RAII的设计思路还要⽅便资源的访问所以智能指针类还会想迭代器类⼀样重载 operator*/operator/operator[] 等运算符⽅便访问资源。templateclass T class SmartPtr { public: // RAII SmartPtr(T* ptr) :_ptr(ptr) {} ~SmartPtr() { cout delete[] _ptr endl; delete[] _ptr; } // 重载运算符模拟指针的⾏为⽅便访问资源 T operator*() { return *_ptr; } T* operator-() { return _ptr; } T operator[](size_t i) { return _ptr[i]; } private: T* _ptr; }; double Divide(int a, int b) { // 当b 0时抛出异常 if (b 0) { throw Divide by zero condition!; } else { return (double)a / (double)b; } } void Func() { // 这⾥使⽤RAII的智能指针类管理new出来的数组以后程序简单多了 SmartPtrint sp1 new int[10]; SmartPtrint sp2 new int[10]; for (size_t i 0; i 10; i) { sp1[i] sp2[i] i; } int len, time; cin len time; cout Divide(len, time) endl; } int main() { try { Func(); } catch (const char* errmsg) { cout errmsg endl; } catch (const exception e) { cout e.what() endl; } catch (...) { cout 未知异常 endl; } return 0; }C标准库智能指针的使⽤• C标准库中的智能指针都在这个头⽂件下⾯我们包含就可以是使⽤了智能指针有好⼏种除了weak_ptr他们都符合RAII和像指针⼀样访问的⾏为原理上⽽⾔主要是解决智能指针拷⻉时的思路不同。• auto_ptr是C98时设计出来的智能指针他的特点是拷⻉时把被拷⻉对象的资源的管理权转移给拷⻉对象这是⼀个⾮常糟糕的设计因为他会到被拷⻉对象悬空访问报错的问题C11设计出新的智能指针后强烈建议不要使⽤auto_ptr。其他C11出来之前很多公司也是明令禁⽌使⽤这个智能指针的。• unique_ptr是C11设计出来的智能指针他的名字翻译出来是唯⼀指针他的特点的不⽀持拷⻉只⽀持移动。如果不需要拷⻉的场景就⾮常建议使⽤他。• shared_ptr是C11设计出来的智能指针他的名字翻译出来是共享指针他的特点是⽀持拷⻉也⽀持移动。如果需要拷⻉的场景就需要使⽤他了。底层是⽤引⽤计数的⽅式实现的。• weak_ptr是C11设计出来的智能指针他的名字翻译出来是弱指针他完全不同于上⾯的智能指针他不⽀持RAII也就意味着不能⽤它直接管理资源weak_ptr的产⽣本质是要解决shared_ptr的⼀个循环引⽤导致内存泄漏的问题。具体细节下⾯我们再细讲。• 智能指针析构时默认是进⾏delete释放资源这也就意味着如果不是new出来的资源交给智能指针管理析构时就会崩溃。智能指针⽀持在构造时给⼀个删除器所谓删除器本质就是⼀个可调⽤对象这个可调⽤对象中实现你想要的释放资源的⽅式当构造智能指针时给了定制的删除器在智能指针析构时就会调⽤删除器去释放资源。因为new[]经常使⽤所以为了简洁⼀点unique_ptr和shared_ptr都特化了⼀份[]的版本使⽤时 unique_ptrDate[] up1(newDate[5]);shared_ptrDate[] sp1(new Date[5]); 就可以管理new []的资源。• template class T, class… Args shared_ptr make_shared(Args… args);• shared_ptr 除了⽀持⽤指向资源的指针构造还⽀持 make_shared ⽤初始化资源对象的值直接构造。• shared_ptr 和 unique_ptr 都⽀持了operator bool的类型转换如果智能指针对象是⼀个空对象没有管理资源则返回false否则返回true意味着我们可以直接把智能指针对象给if判断是否为空。• shared_ptr 和 unique_ptr 都得构造函数都使⽤explicit 修饰防⽌普通指针隐式类型转换成智能指针对象。struct Date { int _year; int _month; int _day; Date(int year 1, int month 1, int day 1) :_year(year) ,_month(month) ,_day(day) {} ~Date() { cout ~Date() endl; } }; int main() { auto_ptrDate ap1(new Date); // 拷⻉时管理权限转移被拷⻉对象ap1悬空 auto_ptrDate ap2(ap1); // 空指针访问ap1对象已经悬空 //ap1-_year; unique_ptrDate up1(new Date); // 不⽀持拷⻉ //unique_ptrDate up2(up1); // ⽀持移动但是移动后up1也悬空所以使⽤移动要谨慎 unique_ptrDate up3(move(up1)); shared_ptrDate sp1(new Date); // ⽀持拷⻉ shared_ptrDate sp2(sp1); shared_ptrDate sp3(sp2); cout sp1.use_count() endl; sp1-_year; cout sp1-_year endl; cout sp2-_year endl; cout sp3-_year endl; // ⽀持移动但是移动后sp1也悬空所以使⽤移动要谨慎 shared_ptrDate sp4(move(sp1)); return 0; }1 templateclass T 2 void DeleteArrayFunc(T* ptr) 3 { 4 delete[] ptr; 5 } 6 7 templateclass T 8 class DeleteArray 9 { 10 public: 11 void operator()(T* ptr) 12 { 13 delete[] ptr; 14 } 15 }; 16 17 class Fclose 18 { 19 public: 20 void operator()(FILE* ptr) 21 { 22 cout fclose: ptr endl; 23 fclose(ptr); 24 } 25 }; 26 27 int main() 28 { 29 // 这样实现程序会崩溃 30 // unique_ptrDate up1(new Date[10]); 31 // shared_ptrDate sp1(new Date[10]); 32 33 // 解决⽅案1 34 // 因为new[]经常使⽤所以unique_ptr和shared_ptr 35 // 实现了⼀个特化版本这个特化版本析构时⽤的delete[] 36 unique_ptrDate[] up1(new Date[5]); 37 shared_ptrDate[] sp1(new Date[5]); 38 39 // 解决⽅案2 40 41 // 仿函数对象做删除器 42 //unique_ptrDate, DeleteArrayDate up2(new Date[5], DeleteArrayDate ()); 43 // unique_ptr和shared_ptr⽀持删除器的⽅式有所不同 44 // unique_ptr是在类模板参数⽀持的shared_ptr是构造函数参数⽀持的 45 // 这⾥没有使⽤相同的⽅式还是挺坑的 46 // 使⽤仿函数unique_ptr可以不在构造函数传递因为仿函数类型构造的对象直接就可以调⽤ 47 // 但是下⾯的函数指针和lambda的类型不可以 48 unique_ptrDate, DeleteArrayDate up2(new Date[5]); 49 shared_ptrDate sp2(new Date[5], DeleteArrayDate()); 50 51 // 函数指针做删除器 52 unique_ptrDate, void(*)(Date*) up3(new Date[5], DeleteArrayFuncDate); 53 shared_ptrDate sp3(new Date[5], DeleteArrayFuncDate); 54 55 // lambda表达式做删除器 56 auto delArrOBJ [](Date* ptr) {delete[] ptr; }; 57 unique_ptrDate, decltype(delArrOBJ) up4(new Date[5], delArrOBJ); 58 shared_ptrDate sp4(new Date[5], delArrOBJ); 59 60 // 实现其他资源管理的删除器 61 shared_ptrFILE sp5(fopen(Test.cpp, r), Fclose()); 62 shared_ptrFILE sp6(fopen(Test.cpp, r), [](FILE* ptr) { 63 cout fclose: ptr endl; 64 fclose(ptr); 65 }); 66 67 return 0; 68 }1 int main() 2 { 3 shared_ptrDate sp1(new Date(2024, 9, 11)); 4 shared_ptrDate sp2 make_sharedDate(2024, 9, 11); 5 auto sp3 make_sharedDate(2024, 9, 11); 6 shared_ptrDate sp4; 7 8 // if (sp1.operator bool()) 9 if (sp1) 10 cout sp1 is not nullptr endl; 11 12 if (!sp4) 13 cout sp1 is nullptr endl; 14 15 // 报错 16 shared_ptrDate sp5 new Date(2024, 9, 11); 17 unique_ptrDate sp6 new Date(2024, 9, 11); 18 19 return 0; 20 }智能指针的原理• 下⾯我们模拟实现了auto_ptr和unique_ptr的核⼼功能这两个智能指针的实现⽐较简单⼤家了解⼀下原理即可。auto_ptr的思路是拷⻉时转移资源管理权给被拷⻉对象这种思路是不被认可的也不建议使⽤。unique_ptr的思路是不⽀持拷⻉。• ⼤家重点要看看shared_ptr是如何设计的尤其是引⽤计数的设计主要这⾥⼀份资源就需要⼀个引⽤计数所以引⽤计数才⽤静态成员的⽅式是⽆法实现的要使⽤堆上动态开辟的⽅式构造智能指针对象时来⼀份资源就要new⼀个引⽤计数出来。多个shared_ptr指向资源时就引⽤计数shared_ptr对象析构时就–引⽤计数引⽤计数减到0时代表当前析构的shared_ptr是最后⼀个管理资源的对象则析构资源。#pragma once #includefunctional namespace xyp { templateclass T class shared_ptr { public: explicit shared_ptr(T* ptr nullptr) : _ptr(ptr) , _pcount(new atomicint(1)) { } templateclass D explicit shared_ptr(T* ptr, D del) : _ptr(ptr) , _pcount(new atomicint(1)) , _del(del) { } shared_ptr(const shared_ptrT sp) :_ptr(sp._ptr) , _pcount(sp._pcount) , _del(sp._del) { (*_pcount); } void release() { if (--(*_pcount) 0) { //delete _ptr; _del(_ptr); delete _pcount; _ptr nullptr; _pcount nullptr; } } // sp1 sp4; shared_ptrT operator(const shared_ptrT sp) { if (this ! sp) { release(); _ptr sp._ptr; _pcount sp._pcount; _del sp._del; (*_pcount); } return *this; } ~shared_ptr() { release(); } T operator*() { return *_ptr; } T* operator-() { return _ptr; } T* get() const { return _ptr; } int use_count() const { return *_pcount; } operator bool() { return _ptr ! nullptr; } private: T* _ptr; //int* _pcount; atomicint* _pcount; std::functionvoid(T*) _del [](T* ptr) {delete ptr; }; }; }shared_ptr和weak_ptrshared_ptr循环引⽤问题shared_ptr⼤多数情况下管理资源⾮常合适⽀持RAII也⽀持拷⻉。但是在循环引⽤的场景下会导致资源没得到释放内存泄漏所以我们要认识循环引⽤的场景和资源没释放的原因并且学会使⽤weak_ptr解决这种问题。• 如下图所述场景n1和n2析构后管理两个节点的引⽤计数减到1右边的节点什么时候释放呢左边节点中的_next管着呢_next析构后右边的节点就释放了。_next什么时候析构呢_next是左边节点的的成员左边节点释放next就析构了。_3. 左边节点什么时候释放呢左边节点由右边节点中的_prev管着呢_prev析构后左边的节点就释放了。_prev什么时候析构呢_prev是右边节点的成员右边节点释放_prev就析构了。• ⾄此逻辑上成功形成回旋镖似的循环引⽤谁都不会释放就形成了循环引⽤导致内存泄漏• 把ListNode结构体中的_next和_prev改成weak_ptrweak_ptr绑定到shared_ptr时不会增加它的引⽤计数_next和_prev不参与资源释放管理逻辑就成功打破了循环引⽤解决了这⾥的问题struct ListNode { int _data; /*shared_ptrListNode _prev; shared_ptrListNode _next;*/ weak_ptrListNode _prev; weak_ptrListNode _next; ~ListNode() { cout ~ListNode() endl; } }; int main() { /*ListNode* n1 new ListNode; ListNode* n2 new ListNode; delete n1; delete n2;*/ shared_ptrListNode n1(new ListNode); shared_ptrListNode n2(new ListNode); n1-_next n2; n2-_prev n1; return 0; }weak_ptr• weak_ptr不⽀持RAII也不⽀持访问资源所以我们看⽂档发现weak_ptr构造时不⽀持绑定到资源只⽀持绑定到shared_ptr绑定到shared_ptr时不增加shared_ptr的引⽤计数那么就可以解决上述的循环引⽤问题。• weak_ptr也没有重载operator*和operator-等因为他不参与资源管理那么如果他绑定的shared_ptr已经释放了资源那么他去访问资源就是很危险的。weak_ptr⽀持expired检查指向的资源是否过期use_count也可获取shared_ptr的引⽤计数weak_ptr想访问资源时可以调⽤lock返回⼀个管理资源的shared_ptr如果资源已经被释放返回的shared_ptr是⼀个空对象如果资源没有释放则通过返回的shared_ptr访问资源是安全的。int main() { std::shared_ptrstring sp1(new string(111111)); std::shared_ptrstring sp2(sp1); std::weak_ptrstring wp sp1; cout wp.expired() endl; cout wp.use_count() endl; // sp1和sp2都指向了其他资源则weak_ptr就过期了 sp1 make_sharedstring(222222); cout wp.expired() endl; cout wp.use_count() endl; sp2 make_sharedstring(333333); cout wp.expired() endl; cout wp.use_count() endl; wp sp1; //std::shared_ptrstring sp3 wp.lock(); auto sp3 wp.lock(); cout wp.expired() endl; cout wp.use_count() endl; *sp3 ###; cout *sp1 endl; return 0; }shared_ptr的线程安全问题• shared_ptr的引⽤计数对象在堆上如果多个shared_ptr对象在多个线程中进⾏shared_ptr的拷⻉析构时会访问修改引⽤计数就会存在线程安全问题所以shared_ptr引⽤计数是需要加锁或者原⼦操作保证线程安全的。• shared_ptr指向的对象也是有线程安全的问题的但是这个对象的线程安全问题不归shared_ptr管它也管不了应该有外层使⽤shared_ptr的⼈进⾏线程安全的控制。C11和boost中智能指针的关系• Boost库是为C语⾔标准库提供扩展的⼀些C程序库的总称Boost社区建⽴的初衷之⼀就是为C的标准化⼯作提供可供参考的实现Boost社区的发起⼈Dawes本⼈就是C标准委员会的成员之⼀。在Boost库的开发中Boost社区也在这个⽅向上取得了丰硕的成果C11及之后的新语法和库有很多都是从Boost中来的。• C 98 中产⽣了第⼀个智能指针auto_ptr。• C boost给出了更实⽤的scoped_ptr/scoped_array和shared_ptr/shared_array和weak_ptr等.• C TR1引⼊了shared_ptr等不过注意的是TR1并不是标准版。• C 11引⼊了unique_ptr和shared_ptr和weak_ptr。需要注意的是unique_ptr对应boost的scoped_ptr。并且这些智能指针的实现原理是参考boost中的实现的。内存泄漏什么是内存泄漏内存泄漏的危害什么是内存泄漏内存泄漏指因为疏忽或错误造成程序未能释放已经不再使⽤的内存⼀般是忘记释放或者发⽣异常释放程序未能执⾏导致的。内存泄漏并不是指内存在物理上的消失⽽是应⽤程序分配某段内存后因为设计错误失去了对该段内存的控制因⽽造成了内存的浪费。内存泄漏的危害普通程序运⾏⼀会就结束了出现内存泄漏问题也不⼤进程正常结束⻚表的映射关系解除物理内存也可以释放。⻓期运⾏的程序出现内存泄漏影响很⼤如操作系统、后台服务、⻓时间运⾏的客⼾端等等不断出现内存泄漏会导致可⽤内存不断变少各种功能响应越来越慢最终卡死。如何避免内存泄漏• ⼯程前期良好的设计规范养成良好的编码规范申请的内存空间记着匹配的去释放。ps这个理想状态。但是如果碰上异常时就算注意释放了还是可能会出问题。需要下⼀条智能指针来管理才有保证。• 尽量使⽤智能指针来管理资源如果⾃⼰场景⽐较特殊采⽤RAII思想⾃⼰造个轮⼦管理。• 定期使⽤内存泄漏⼯具检测尤其是每次项⽬快上线前不过有些⼯具不够靠谱或者是收费。• 总结⼀下内存泄漏⾮常常⻅解决⽅案分为两种1、事前预防型。如智能指针等。2、事后查错型。如泄漏检测⼯具。
版权声明:本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!

大良手机网站建设yw193can未满十8麻豆

测绘人员必备:CASS和CAD分地分割面积插件终极指南 【免费下载链接】cass和CAD分地分割面积插件 这款**cass和CAD分地分割面积插件**是专为地籍测绘人员打造的高效工具,兼容cass和CAD软件,轻松实现地块分割与面积计算。其特点包括强大的兼容性…

张小明 2025/12/28 23:54:46 网站建设

网上书店网站建设实训报告总结wap网站的发展

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容: 设计一个适合新手的简单网页,展示动态变化的666数字。要求:1)页面背景渐变 2)中央显示放大的666数字 3)数字要有简单的放大缩小动画 4)底部添加点击刷新按钮…

张小明 2025/12/29 0:37:23 网站建设

福建泉州做网站公司哪家好wordpress修改html

根据《中华人民共和国无线电管理条例》,凡在中国境内生产、销售或进口,主动发射无线电波的设备(除豁免类别外),均需申请 SRRC 型号核准并标注 CMIIT ID。以下是核心产品范围与豁免说明,便于快速判断&#x…

张小明 2025/12/29 4:31:52 网站建设

鹤壁百度网站建设鲜花网站建设方案

第一章:Open-AutoGLM自动提醒设置概述Open-AutoGLM 是一款基于大语言模型的自动化任务调度与提醒系统,支持用户根据自定义规则配置实时提醒机制。该系统广泛应用于运维监控、数据管道告警以及智能客服场景中,能够有效提升响应效率并降低人工干…

张小明 2025/12/28 12:49:37 网站建设

17zwd一起做业网站软装设计网站有哪些

简介 什么是 Hemmelig ? Hemmelig 是一个自托管的应用程序,用于安全地共享敏感信息,采用客户端加密和自销毁消息的功能。用户可以通过 Hemmelig 分享加密的秘密,这些秘密在查看后或到期后将被自动删除,确保信息不被存…

张小明 2025/12/29 4:31:56 网站建设

辽宁网站seo网站开发 jsp开发工具

北京——近日,昆山海菲曼科技集团股份有限公司(以下简称“海菲曼”)在北京证券交易所完成首次公开发行(IPO)过会,计划募集资金4.30亿元用于声学元器件与整机产能提升、纳米振膜及工业DAC芯片研发中心建设以…

张小明 2025/12/29 4:31:55 网站建设