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

民宿行业网站建设方案qq官方网站登录入口

民宿行业网站建设方案,qq官方网站登录入口,wordpress购物车显示,模板王网站目录 智能指针意义 智能指针的使用及原理 RAII 智能指针的原理 std::auto_ptr std::auto_ptr的模拟实现 std::unique_ptr std::unique_ptr模拟实现 std::shared_ptr std::shared_ptr的模拟实现 循环引用问题 智能指针意义 #问#xff1a;为什么需要智能指针#…目录 智能指针意义 智能指针的使用及原理 RAII 智能指针的原理 std::auto_ptr std::auto_ptr的模拟实现  std::unique_ptr std::unique_ptr模拟实现 std::shared_ptr std::shared_ptr的模拟实现 循环引用问题 智能指针意义 #问为什么需要智能指针 #include iostream #include stdexceptint div() {int a, b;std::cin a b;if (b 0)throw std::invalid_argument(除0错误);return a / b; }void Func() {// 1、如果p1这里new 可能会抛异常。// 2、如果p2这里new 可能会抛异常。// 3、如果div调用也可能会抛异常。int *p1 new int;int *p2 new int;std::cout div() std::endl;delete p1;delete p2; }int main() {try{Func();}catch (std::exception e){std::cout e.what() std::endl;}return 0; } 在一异常中因为异常会导致程序的执行流乱跳所以很多个会出现异常的代码放在一起就很容易其中一个抛异常而导致其余的未执行 / 需要释放的空间未释放。如上p2出问题需要释放p1div出问题需要释放p1、p2智能指针就是用来解决这个问题。 智能指针的使用及原理 RAII RAIIResource Acquisition Is Initialization - 获取资源即初始化是一种利用对象生命周期来控制程序资源如内存、文件句柄、网络连接、互斥量等等的简单技术。资源需要手动释放的。RAII请求到志愿就初始化 初始化指的是        调用一个其他类的构造函数利用其他类的生命周期来进行管理。 在对象构造时获取资源接着控制对资源的访问使之在对象的生命周期内始终保持有效最后在对象析构的时候释放资源。借此我们实际上把管理一份资源的责任托管给了一个对象。 就是在获取到资源的时候交给一个对象管理于是在该对象的生命周期里这个资源始终有效。而这个对象无论如何是异常还是正常结束都会调用这个对象的析构函数于是利用这个对象的析构函数释放资源。 这种做法有两大好处 不需要显式地释放资源。 采用这种方式对象所需的资源在其生命期内始终保持有效。 智能指针的原理 最基础的智能指针 // 使用RAII思想设计的SmartPtr类 template class T class SmartPtr { public:SmartPtr(T *ptr nullptr) // 将资源给智能指针: _ptr(ptr) // 智能指针将资源保存{}~SmartPtr(){if (_ptr)delete _ptr;}private:T *_ptr; }; 上述的SmartPtr还不能将其称为智能指针因为它还不具有指针的行为。指针可以解引用也可以通过-去访问所指空间中的内容因此智能指针模板类中还得需要将* 、-重载下才可让其像指针一样去使用。 #include iostream #include stdexcept// 1、利用RAII思想设计delete资源的类 // 2、像指针一样的行为 templateclass T class SmartPtr { public:SmartPtr(T* ptr) // 将资源给智能指针:_ptr(ptr) // 智能指针将资源保存{}~SmartPtr(){cout delete: _ptr endl;delete _ptr;}T operator*(){return *_ptr;}T* operator-(){return _ptr;}private:T* _ptr; };int div() {int a, b;std::cin a b;if (b 0)throw std::invalid_argument(除0错误);return a / b; } void Func() {// sp1、sp2出作用域会调用析构函数抛异常栈帧会正常结束SmartPtrint sp1(new int);SmartPtrint sp2(new int);*sp1 0;*sp2 2;std::cout div() std::endl; }int main() {try{Func();}catch (std::exception e){std::cout e.what() std::endl;}return 0; } 总结一下智能指针的原理 RAII特性。重载operator*和opertaor-具有像指针一样的行为。Note         智能指针看起来很完美但是又一个致命的问题智能指针的拷贝问题。默认的拷贝构造只会进行浅拷贝就会导致一个地址被析构两次。主要原因就是智能指针管理资源的释放。 解决方案 问深拷贝 不能违背了智能指针的功能需求需要的就是浅拷贝智能指针不知道该空间有多大只是对与指针的保存。 问题先保留看看C库中的解决方式 std::auto_ptr http://www.cplusplus.com/reference/memory/auto_ptr/ C98版本的库中就提供了auto_ptr的智能指针。auto_ptr的实现原理管理权转移的思想下面简化模拟实现了一份bit::auto_ptr来了解它的原理。#include iostream #include memoryclass A { public:~A(){std::cout ~A() std::endl;}int _a1 0;int _a2 0; };int main() {std::auto_ptrA ap1(new A);ap1-_a1;ap1-_a2;std::auto_ptrA ap2(ap1);//ap1-_a1;//ap1-_a2;return 0; } 正是这个原因所以ap1就空了。总结         std::auto_ptr是采用的资源管理权转移。但是是不负责任的拷贝会导致被拷贝对象悬空。所以多年以来被挂在耻辱柱上很多公司明确要求不能使用它。 std::auto_ptr的模拟实现  注意不是交换 —— 是管理权的转移所以如果是 std::auto_ptrA ap1(new A); std::auto_ptrA ap2(new A); ap2 ap1; ap2是获取ap1的资源资源管理权的转移 ap2之前的资源自动调用析构释放ap1置空nullptr。 namespace cr {templateclass Tclass auto_ptr {public:auto_ptr(T* ptr nullptr): _ptr(ptr){}// 不是交换 —— 是管理权的转移// 不是交换auto_ptr(auto_ptrT ap):_ptr(ap._ptr){ap._ptr nullptr;}// 不是交换 —— 是管理权的转移// ap1 ap2;auto_ptrT operator(auto_ptrT ap){if (this ! ap){if (_ptr){cout Delete: _ptr endl;delete _ptr;}_ptr ap._ptr;ap._ptr nullptr;}return *this;}~auto_ptr(){if (_ptr){cout Delete: _ptr endl;delete _ptr;}}T operator*(){return *_ptr;}T* operator-(){return _ptr;}private:T* _ptr;}; } std::unique_ptr C11中开始提供更靠谱的unique_ptr https://cplusplus.com/reference/memory/unique_ptr/ unique_ptr的实现原理不让你拷贝简单粗暴的防拷贝下面简化模拟实现了一份UniquePtr来了解它的原理。只适用于不需要拷贝的场景。std::unique_ptr模拟实现 namespace cr {templateclass Tclass unique_ptr{private: // 防止有人跑到类外实现写一个浅拷贝// 防拷贝 C98 - 当时还是boost库中// 只声明不实现 // unique_ptr(unique_ptrT ap);// unique_ptrT operator(unique_ptrT ap);public:unique_ptr(T* ptr nullptr): _ptr(ptr){}// 防拷贝 C11unique_ptr(unique_ptrT ap) delete;unique_ptrT operator(unique_ptrT ap) delete;~unique_ptr(){if (_ptr){cout Delete: _ptr endl;delete _ptr;}}T operator*(){return *_ptr;}T* operator-(){return _ptr;}private:T* _ptr;}; } std::shared_ptr C11中开始提供更靠谱的并且支持拷贝的shared_ptr 。 www.cplusplus.com/reference/memory/shared_ptr/#include memory #include iostreamclass A { public:~A(){std::cout ~A() std::endl;}int _a1 0;int _a2 0; };void test_shared_ptr() {std::shared_ptrA sp1(new A);std::shared_ptrA sp2(sp1);sp1-_a1;sp1-_a2;std::cout sp2-_a1 : sp2-_a2 std::endl;sp2-_a1;sp2-_a2;std::cout sp1-_a1 : sp1-_a2 std::endl; }int main() {test_shared_ptr();return 0; } shared_ptr的原理是通过引用计数的方式来实现多个shared_ptr对象之间共享资源。例如 学校老师晚上在下班之前都会通知让最后走的学生记得把门锁下并且打扫一下教室。 shared_ptr在其内部给每个资源都维护了着一份计数用来记录该份资源被几个对象共享。 在对象被销毁时(也就是析构函数调用)就说明自己不使用该资源了对象的引用计数减一。 如果引用计数是0就说明自己是最后一个使用该资源的对象必须释放该资源 如果不是0就说明除了自己还有其他对象在使用该份资源不能释放该资源否则其他对象就成野指针了。 std::shared_ptr的模拟实现 不能用static修饰计数器因为这样会让所有的模拟实现的shared_ptr的不同类型的实例化同用一个计数器。需要的是一个资源配一个计数器多个智能指针对象共管静态计数对象所以资源都只有一个计数因为静态成员属于整个类属于类的所有对象。 所以使用的是一个指针这个时候这个指针指向的空间就是new出来的使用构造函数new这就保证了同一个资源用一个计数器。并且这样这个指针就会指向需释放的资源也指向了计数。 即每个资源需要管理的时候会给构造函数构造new一个计数。 namespace cr {templateclass Tclass shared_ptr{public:shared_ptr(T* ptr nullptr): _ptr(ptr), _pCount(new int(1)){}// 判断是否释放void Release(){// 减减被赋值对象的计数如果是最后一个对象要释放资源if (--(*_pCount) 0){cout Delete: _ptr endl;delete _ptr;delete _pCount;}}~shared_ptr(){Release();}// sp1(sp2)shared_ptr(const shared_ptrT sp): _ptr(sp._ptr), _pCount(sp._pCount){(*_pCount);}shared_ptrT operator(const shared_ptrT sp){// 防止自己给自己赋值导致计数--出现内存泄漏if (_ptr sp._ptr){return *this;}// 判断是否释放 -- 防止_ptr原来的数据未计数--导致内存泄漏Release();// 共管新资源计数_ptr sp._ptr;_pCount sp._pCount;(*_pCount);return *this;}T operator*(){return *_ptr;}T* operator-(){return _ptr;}private:T* _ptr;// 引用计数int* _pCount;}; } shared_ptr的问题 shared_ptr看起来很完美但是也有问题 在多线程使用shared_ptr的时候shared_ptr不是线程安全的。shared_ptr存在一个循环引用的问题。 循环引用问题 是一个非常特殊的情况下 #include iostream #include memoryclass Node { public:~Node(){std::cout ~Node std::endl;}int val 0;std::shared_ptrNode _next;std::shared_ptrNode _prev; };void test_shared_ptr() {std::shared_ptrNode s1(new Node);std::shared_ptrNode s2(new Node);s1-_next s2;s2-_prev s1; }int main() {test_shared_ptr();return 0; } 我们可以发现上面代码并没有像我们想象的一样自动调用析构函数 分析 当下图的时候是没有问题的也就是对于shared_ptr智能指针的使用shared_ptr的计数器分别都。 但是当继续向下执行的时候就是问题的关键所在。 此处shared_ptr类型的s1经过operator -的重载于是变为(Node*)-_next s2此处Note中的_next对象是shared_ptr类型的所以会调用s2中的智能指针的赋值。 同理会调用s1中的智能指针的赋值。 于是s1与s2的计数器分别都到了2。 #问通过以上为什么不会调用析构 因为根据函数的创建顺序s2后构造所以先析构s1先构造所以后析构。 于是s2与s1就分别调用它们的析构函数了于是计数器分别都--到了1。但是由于 _next管着右边的节点内存块。_prev管着左边的节点内存块。于是便出现理想状态下_next释放那右边就释放_prev释放那左边就释放。 但是会出现一个问题_next与_prev分别数据不同的成员节点对于对象中的成员是需要该对象调用析构函数才会释放其中的成员于是对于左节点是需要计数器--到0才能释放左节点_next才会析构。同样的右节点是需要计数器--到0才会释放右节点_prev才会析构。 这就是一个死循环所以没有调用Node的析构函数也就不可能看到Node类型对象的析构释放显示。 解决方式 这个地方想使用shared_ptr进行Node类型的对象中类似的操作是把必定错的没有办法所以C也为我们提供了一个新的方式weak_ptr弱指针 weak_ptr与其他的智能指针都不一样其并不是常规智能指针没有RAII不支持直接管理资源。weak_ptr主要用shared_ptr构造用来解决shared_ptr循环引用问题。 https://legacy.cplusplus.com/reference/memory/weak_ptr/?kwweak_ptr 主要用share_ptr来构造自己并不支持用一个资源构造自己所以其并不支持RAII。 特点不share_ptr的计数器。 #include iostream #include memoryclass Node { public:~Node(){std::cout ~Node std::endl;}int val 0;std::weak_ptrNode _next;std::weak_ptrNode _prev; };void test_shared_ptr() {std::shared_ptrNode s1(new Node);std::shared_ptrNode s2(new Node);s1-_next s2;s2-_prev s1; }int main() {test_shared_ptr();return 0; } 当 _next 与 _prev 是 weak_ptr 的时候它们不参加资源的释放管理但是可以访问和修改数据且并不增加计数所以不会存在循环引用的问题了。这个方法可行但是因为不计数多以我们要识别到这个问题 Note         想看到计数的对应变化可以使用shared_ptr的成员函数 use_count 。 weak_ptr的模拟实现 对于前面所模拟实现的shared_ptr同样的也具有循环引用的问题。 #include iostreamnamespace cr {templateclass Tclass shared_ptr{public:shared_ptr(T* ptr nullptr): _ptr(ptr), _pCount(new int(1)){}// 判断是否释放void Release(){// 减减被赋值对象的计数如果是最后一个对象要释放资源if (--(*_pCount) 0){delete _ptr;delete _pCount;}}~shared_ptr(){Release();}// sp1(sp2)shared_ptr(const shared_ptrT sp): _ptr(sp._ptr), _pCount(sp._pCount){(*_pCount);}shared_ptrT operator(const shared_ptrT sp){// 防止自己给自己赋值导致计数--出现内存泄漏if (_ptr sp._ptr)return *this;// 判断是否释放 -- 防止_ptr原来的数据未计数--导致内存泄漏Release();// 共管新资源计数_ptr sp._ptr;_pCount sp._pCount;(*_pCount);return *this;}T operator*(){return *_ptr;}T* operator-(){return _ptr;}private:T* _ptr;// 引用计数int* _pCount;}; }class Node { public:~Node(){std::cout ~Node std::endl;}int val 0;cr::shared_ptrNode _next;cr::shared_ptrNode _prev; };void test_shared_ptr() {cr::shared_ptrNode s1(new Node);cr::shared_ptrNode s2(new Node);s1-_next s2;s2-_prev s1; }int main() {test_shared_ptr();return 0; }于是可以通过模拟实现weak_ptr进行避免我们所模拟实现的shared_ptr出现循环引用的问题。 #include iostreamnamespace cr {template class Tclass shared_ptr{public:shared_ptr(T *ptr nullptr) : _ptr(ptr), _pCount(new int(1)) {}// 判断是否释放void Release(){// 减减被赋值对象的计数如果是最后一个对象要释放资源if (--(*_pCount) 0){delete _ptr;delete _pCount;}}~shared_ptr() { Release(); }// sp1(sp2)shared_ptr(const shared_ptrT sp) : _ptr(sp._ptr), _pCount(sp._pCount) { (*_pCount); }shared_ptrT operator(const shared_ptrT sp){// 防止自己给自己赋值导致计数--出现内存泄漏if (_ptr sp._ptr)return *this;// 判断是否释放 -- 防止_ptr原来的数据未计数--导致内存泄漏Release();// 共管新资源计数_ptr sp._ptr;_pCount sp._pCount;(*_pCount);return *this;}T operator*() { return *_ptr; }T *operator-() { return _ptr; }// 便于外部获取ptr如weak_ptrT *get()const{return _ptr;}private:T *_ptr;// 引用计数int *_pCount;};// 辅助型智能指针使命配合解决shared_ptr循环引用问题template class Tclass weak_ptr{public:weak_ptr(): _ptr(nullptr){}weak_ptr(const shared_ptrT sp): _ptr(sp.get()){}weak_ptr(const weak_ptrT wp): _ptr(wp._ptr){}weak_ptrT operator(const shared_ptrT sp){_ptr sp.get();return *this;}T operator*(){return *_ptr;}T* operator-(){return _ptr;}private:T *_ptr;}; }class Node { public:~Node() { std::cout ~Node std::endl; }int val 0;cr::weak_ptrNode _next;cr::weak_ptrNode _prev; };void test_shared_ptr() {cr::shared_ptrNode s1(new Node);cr::shared_ptrNode s2(new Node);s1-_next s2;s2-_prev s1; }int main() {test_shared_ptr();return 0; } 需要掌握 为什么需要智能指针        主要的原因还是因为内存泄漏忘记释放的问题更重要还有异常安全的问题。 RAII        资源获得资源请求机立即初始化。指的就是把资源交给一个对象利用构造将其资源交给一个对象去管理。 发展历史auto_ptr / unique_ptr / shared_ptr / weak_ptr之间的区别与使用场景。模拟实现简洁版智能指针。什么是循环引用如何解决循环引用解决的原理是什么
http://www.dnsts.com.cn/news/104145.html

相关文章:

  • 新乡网站建设报价定制网站与模板建站维护
  • 长沙网站建设商城设计公司起名大全
  • 苏州吴江做网站公司好域名做网站
  • 一个域名权重3如果做网站的话权重会降为0吗简单建站的网站
  • 百姓网网站建设wordpress仪表盘美化
  • 宁陵做网站关键词推广哪家好
  • 企业网站设计制作收费做竞价网站
  • dw做网站小技巧产品推广网站哪个好
  • 网站建设会议记录惠州网站建设找哪个公司
  • 亿企搜网站建设网页设计作品 简单
  • 做poster的网站曲靖做网站公司
  • 网站设计好不好复杂大型网站建设成本
  • 网站建设优劣的评价标准国外网站如何做seo
  • 网站漏洞解决ps 怎么做网站搜索框
  • 怎么在58建设企业的网站永嘉网站制作哪家好
  • 博物馆设计网站推荐商标注册号查询入口官网
  • 响应式网站应用开发一个app需要什么条件
  • 山东青?u68元建网站哪一些网站使用vue做的
  • 搭建手机网站太原中企动力网站建设
  • 网站建设控制注册网站域名要多少钱
  • 专业建站公司主要做什么河北省建设厅工程信息网站
  • 做网站网站中国设计网络首选品牌
  • 网站建设实训心得体会2000字服装设计师
  • 手机网站素材大连工程建设信息网
  • 温州市住房建设局网站用什么网站开发
  • .我爱你 网站wordpress 滑动解锁
  • 建设市场监督管理网站建设网站如何进行网站备案
  • 客村网站建设商标网商标购买
  • 新乡网站搜索引擎优化网站新域名查询
  • 网站建设上wordpress标签调用