⭐️博主此生决int-CSDN博客速胜派就是最大的投降派热门专栏深入理解 C 系列算法系列快速复习系列Java 速通系列文章目录上期回顾智能指针的使用及其原理1. 智能指针的使用场景分析2. RAII和智能指针的设计思路3. C标准库智能指针的使用3.1 unique_ptr3.2 shared_ptr3.3 shared_ptr 的常用操作循环引用问题4. weak_ptr4. 智能指针的原理4.1 unique_ptr 的原理4.2. shared_ptr6. shared_ptr的线程安全问题8. 内存泄漏8.1 什么是内存泄漏内存泄漏的危害财哥的Linux专栏结语上期回顾智能指针的使用及其原理1. 智能指针的使用场景分析voidFunc(){int*pnewint(10);// 一堆代码……}// 忘记 deletevoidFunc(){int*pnewint(10);if(条件)return;deletep;}voidFunc(){int*pnewint(10);throwexception();deletep;}非常的难用容易忘记并且内存泄漏很危险所以我们可不可以类比自定义类型的自动析构呢就是把指针放到一个对象里然后指针申请的资源随对象的创建而创建随对象的析构而销毁——智能指针手动管理资源最大的麻烦不是不会delete而是很难保证所有路径都正确地delete。2. RAII和智能指针的设计思路RAII把资源交给对象管理利用对象的生命周期自动释放资源。最简单的智能指针templateclassTclassSmartPtr//把指针当到一个对象里自动申请和释放资源{public:SmartPtr(T*ptr):_ptr(ptr){}~SmartPtr(){delete_ptr;}private:T*_ptr;};智能指针本质上不是“更智能的指针”而是“利用对象生命周期管理指针所指向资源的类”。上面只是实现了指针最基础的版本把他放进一个类里面但是这个设计还有很多缺点例如当两个及以上的指针指向同一块资源时就会发生多次析构进而多次释放同一块空间所以c针对不同的应用场景设计了三种不同的指针unique_ptr、shared_ptr、weak_ptr3. C标准库智能指针的使用unique_ptr独占资源不能拷贝只能移动。shared_ptr共享资源通过引用计数决定什么时候释放。weak_ptr不拥有资源只观察shared_ptr管理的资源不增加强引用计数。3.1unique_ptr一个资源只能有一个unique_ptr拥有。#includememoryunique_ptrintp(newint(10));//更推荐unique_ptrintpmake_uniqueint(10);顾名思义是单独的只能一个对象管理一份资源所以unique_ptr不能进行普通拷贝但是它可以移动3.2shared_ptr允许多个智能指针共同拥有同一份资源。shared_ptrintp1make_sharedint(10);shared_ptrintp2p1;实现两个对象指向同一个资源是怎么实现的呢——引用计数引用计数计数有几个对象指向对应的资源就是几shared_ptr只有在最后一个拥有者消失时即引用计数为0时才会释放资源。3.3shared_ptr的常用操作use_count()返回目前引用计数为几reset()让当前shared_ptr放弃所有权对应的引用计数减一如果减完后为0就销毁资源。例如shared_ptrintp1make_sharedint(10);coutp1.use_count()endl;// 1shared_ptrintp2p1;coutp1.use_count()endl;// 2shared_ptrintp3make_sharedint(10);p3.reset();//引用计数减一变为0销毁shared_ptrintp4make_sharedint(10);//引用计数1shared_ptrintp5p4;//引用计数2p4.reset();//引用计数1我们看其实shaered_ptr已经够用了已经非常完美了甚至都不用unique_ptr了但是有一个致命问题——循环引用问题循环引用问题简单来说就是来看下面这段代码structListNode{int_data;std::shared_ptrListNode_next;std::shared_ptrListNode_prev;//注意这里用的都是shared——ptr~ListNode(){cout~ListNode()endl;}};intmain(){// 循环引用 -- 内存泄露std::shared_ptrListNoden1(newListNode);std::shared_ptrListNoden2(newListNode);n1-_nextn2;n2-_prevn1;//导致循环引用return0;}当他们析构时所以为了解决这个问题就引入了——weak_ptr4.weak_ptrweak_ptr不拥有资源。只监管资源查看不改变引用计数例如shared_ptrintpmake_sharedint(10);coutp.use_count()endl;// 1weak_ptrintwp;coutp.use_count()endl;// 仍然是 1总结unique_ptr独占资源不能拷贝只能移动。shared_ptr共享资源通过引用计数决定什么时候释放。weak_ptr不拥有资源只观察shared_ptr管理的资源不增加强引用计数。4. 智能指针的原理4.1unique_ptr的原理templateclassTclassMyUniquePtr{public:MyUniquePtr(T*ptr):_ptr(ptr){}~MyUniquePtr(){delete_ptr;}MyUniquePtr(constMyUniquePtr)delete;//不允许拷贝MyUniquePtroperator(constMyUniquePtr)delete;MyUniquePtr(MyUniquePtrother)//不能拷贝可以移动{_ptrother._ptr;other._ptrnullptr;}private:T*_ptr;};把资源的所有权拿过来然后让原对象放弃所有权。4.2. shared_ptrshared_ptr的核心就是多个shared_ptr共享一个引用计数。引用计数用什么来实现呢因为是多个对象共有的所以可以在堆上申请一块空间用来保存代码templateclassTclassMySharedPtr{private:T*_ptr;int*_pcount;//引用计数};财哥有疑问为什么不能用静态变量很简单因为静态变量是属于类的如果你用静态变量来存储那么你所有的智能指针都用同一个引用计数这显然不是我们想要的那么我们要如何管理引用计数呢——通过int*指针来管理templateclassTclassMySharedPtr{public:MySharedPtr(T*ptr):_ptr(ptr),_pcount(newint(1))//默认为1{}MySharedPtr(constMySharedPtrsp)//拷贝构造:_ptr(sp._ptr),_pcount(sp._pcount){(*_pcount);//引用计数1}~MySharedPtr(){if(--(*_pcount)0)//先引用计数--只有为0才销毁资源{delete_ptr;delete_pcount;}}private:T*_ptr;int*_pcount;};我们这里实现的是简化后的版本实际库里面的比这复杂的多用到了强引用计数和弱引用计数感兴趣可以去看源码总结如果一个资源天然就应该只有一个拥有者那么unique_ptr就很合适如果确实存在多个对象共同拥有资源的情况才需要shared_ptr。6. shared_ptr的线程安全问题**shared_ptr的引用计数操作通常是线程安全的但shared_ptr管理的对象本身不一定是线程安全的。具体后面学到线程部分会详细讲解总之记住shared_ptr的引用计数操作通常是线程安全的但shared_ptr管理的对象本身不一定是线程安全的。意思就是指针里面指向的内容在被同时修改时会得到我们预期不一样的结果面试问到就答shared_ptr的引用计数管理具有线程安全保证但它不保证所管理对象的线程安全也不能让同一个shared_ptr对象的并发读写自动变得安全。8. 内存泄漏8.1 什么是内存泄漏内存泄漏的危害内存泄漏Memory Leak程序申请的动态内存没有被正确释放并且已经无法再访问这块内存。典型的例子就是申请了空间没有释放new/malloc后没有delete和free危害主要是对于长时间运行的服务器或者程序我们写代码时的内存泄漏操作系统会在我们关闭程序后全部收回主要危害发在下面这几种情况长时间运行的服务器程序后台服务游戏高并发程序数据库等长期运行的软件好了那么到现在为止所有的C相关的基础知识什么就已经学习完了真棒!!!但是这仅仅只是我们学习路上的开始后面还有很多很多知识等待着我们去学习与探索加油少年下系列预告——Linux系统带你从入门到完全理解操作系统和网络我们下一系列再见财哥的Linux专栏结语本文到此结束感谢大家的阅读如果觉得本文对你有所帮助欢迎点赞、收藏、关注也欢迎在评论区一起交流讨论。也欢迎订阅我的深入理解 C系列从语法入门到底层原理系统掌握现代 C算法系列从入门到精通蓝桥杯、ACM、LeetCode 与面试算法全路线快速复习系列知识梳理、查漏补缺考前冲刺必备Java 速通系列已学 C 语言快速上手 Java轻松备战期末考试愿每一次敲下键盘都比昨天更进一步愿每一行代码落下都让未来多一种可能
