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

网站建设运营公司大全宁夏省建设厅网站

网站建设运营公司大全,宁夏省建设厅网站,无极网最新招聘信息,网页游戏平台网站🦄个人主页:修修修也 🎏所属专栏:C ⚙️操作环境:Visual Studio 2022 目录 为什么需要智能指针 智能指针的使用及其实现原理 RAII auto_ptr 简介 实现 unique_ptr 简介 实现 shared_ptr 简介 实现 weak_ptr 简介 实现 结语 为什么需要智能指针 C没有垃圾…

🦄个人主页:修修修也

🎏所属专栏:C++

⚙️操作环境:Visual Studio 2022


目录

为什么需要智能指针

智能指针的使用及其实现原理

RAII

auto_ptr

简介

实现

unique_ptr

简介

实现

shared_ptr

简介

实现

weak_ptr

简介

实现

结语


为什么需要智能指针

        C++没有垃圾回收的机制,必须通过我们手动的去动态申请并释放资源。也就是说, 我们new出的资源, 必须在后面不使用之后将其delete掉, 否则就会造成内存泄漏。

        我在【C++】动态内存管理中详细介绍过内存泄漏的危害, 并提供了几种防止内存泄漏的方式, 其中最重要的一点就是要严格遵守谁申请谁释放原则, 这样就可以避免大量的内存泄漏场景, 一般而言,只要内存遵行了先申请后释放的原则, 那么100%是不可能内存泄漏的, 但是当C++引入异常这一特性的时候, 一切都变得不一样了...

        我们来看这段代码, 分析一下下面三种情况程序会出现什么问题:

int div()
{int a, b;cin >> a >> b;if (b == 0)throw invalid_argument("除0错误");return a / b;
}void Func()
{// 1、如果p1这里new 抛异常会如何?// 2、如果p2这里new 抛异常会如何?// 3、如果div调用这里又会抛异常会如何?int* p1 = new int;int* p2 = new int;cout << div() << endl;delete p1;delete p2;
}int main()
{try{Func();}catch (exception& e){cout << e.what() << endl;}return 0;
}

        不难发现,除了p1抛异常,剩下的两种情况都会导致不同程度的内存泄漏:

        那么是不是有异常的时候我们只能对着在执行流里乱窜的异常说:"太好了孩子们,是异常,我们没救了😅"。当然不是!!!乱世之中, 咱们的救世主悄然登场了:


智能指针的使用及其实现原理

        没错,智能指针就是救我们与水火之中的救世主, 那他的原理是什么呢?我们先来了解RAII思想:

RAII

        RAII(Resource Acquisition Is Initialization)是一种利用对象生命周期来控制程序资源(如内存、文件句柄、网络连接、互斥量等等)的简单技术。

        它是在对象构造时获取资源, 接着控制对资源的访问使之在对象的生命周期内始终保持有效, 最后在对象析构时释放资源。因此, 我们实际上是把管理一份资源的责任托管给了一个对象。这种做法有两大好处:

  • 不需要显式地释放资源
  • 采用这种方式, 对象所需要的资源在其生命周期内始终保持有效

auto_ptr

简介

        借助RAII思想, 我们的初代智能指针auto_ptr闪亮登场, 只是可惜这个初代目不太经打, 刚刚登场, 就已领了盒饭, 以至于后面被很多企业禁止使用, auto_ptr的主要败笔在于, 它在拷贝构造和赋值时使用了管理权转移的思想, 即把b赋值/拷贝构造给a时, 会直接把b的指针给a, 然后b自己置空。这样会导致b指针后续处于一个悬空状态, 后续如果继续不慎使用b则会造成空指针解引用的问题。而且在b生命周期结束后他会去析构一个空指针, 这完全就是一个非法的内存访问操作, 所以不可避免的会导致程序崩溃。如果b指针赋值后不置为空, 那么后续又会出现多重析构的问题。这导致了auto_ptr面世没多久就遭到了"封杀", 实在是可惜。但是智能指针并不因此挫折就销声匿迹了, 有此前车之鉴, 后续大佬们又在auto_ptr的基础上开发出了更加安全, 实用的智能指针。

实现

        以下是auto_ptr的简单模拟实现代码:

namespace test
{template<class T>class auto_ptr{public:auto_ptr(T* ptr = nullptr):_ptr(ptr){}//管理权转移,把ap.ptr的管理权转让给_ptr,然后ap.ptr自己置空auto_ptr(auto_ptr<T>& other): _ptr(other.ptr){other._ptr = nullptr;}~auto_ptr(){if (_ptr)delete _ptr;}T& operator*(){return *_ptr;}T* operator->(){return _ptr;}// 赋值运算符重载,转移所有权auto_ptr& operator=(auto_ptr& other) {if (this != &other) //检查是否自己给自己赋值{delete _ptr;	//先析构(放弃)自己原有的指针管理权_ptr = other.ptr;	//再拿到新的指针管理权other.ptr = nullptr;	//被转移对象自己置空}return *this;}private:T* _ptr;};
}

unique_ptr

简介

        auto_ptr的惨痛教训还历历在目, 于是C++痛定思痛, 推出了修补版本的unique_ptr。unique_ptr的想法是, 既然auto_ptr的赋值和拷贝构造会导致安全问题, 那么我把这两个操作禁用了不就ok了, 于是我们的二代智能指针就这样登场了。

实现

        unique_ptr在实现上和auto_ptr几乎一模一样, 但是对于拷贝构造函数和赋值运算符重载函数则是直接"封掉":

namespace test
{template<class T>class unique_ptr{public:unique_ptr(T* ptr):_ptr(ptr){}~unique_ptr(){if (_ptr)delete _ptr;}T& operator*(){return *_ptr;}T* operator->(){return _ptr;}//禁止拷贝构造unique_ptr(const unique_ptr& other) = delete;//禁止赋值unique_ptr& operator=(const unique_ptr& other) = delete;private:T* _ptr;};
}

shared_ptr

简介

        unique_ptr的改进为我们提供了相对安全的智能指针的方案, 但是由于他的实现思想的限制, 导致该智能指针在应用上有诸多限制, 例如不可以多个指针管理同一份资源, 也不可以赋值更改管理的资源。为了解决这一问题, 大佬们又出研发了一个史诗级的智能指针, 就是shared_ptr。

        shared_ptr借助了引用计数的思想, 支持多个智能指针管理同一份资源, 允许拷贝构造和赋值, 是通过为一份资源维护一份引用计数来实现的, 该引用计数记录了当前同时管理这份资源的智能指针数, 如果其中一个智能指针超出了生命周期要销毁资源,那么会先判断它是否是当前唯一管理这份资源,即引用计数是否为1, 如果是则析构释放资源, 如果不是那么只会将引用计数-1, 不会真实的去销毁资源。相应的,遇到拷贝构造和赋值则会相应的给引用计数+1。图示如下:

         shared_ptr可以说是智能指针的中流砥柱了, 但是即便如此, 它在某些场景中还是会出现一些无解的问题, 即在某些情况下会出现循环引用问题:

        首先我们可能会遇到使用智能指针管理链表资源的场景:

        然后我们需要将这两个链表结点连接起来:

        看起来好像没一点问题, 但是当我们要释放这两个结点的时候问题就出现了:

实现

        shared_ptr的实现比前面两个稍复杂一点, 引入引用计数后, 我们需要在构造,析构,拷贝构造和赋值函数中对引用计数做相应的处理, 但只要清楚了引用计数的原理,实现起来也非常简单:

namespace test
{template<class T>class shared_ptr{public:shared_ptr(T* ptr):_ptr(ptr),_pcount(new int(1)){}//如果引用计数为1才释放资源,否则只减引用计数~shared_ptr(){if (_ptr){if (*_pcount == 1){delete _ptr;delete _pcount;}else{(* _pcount)--;}}	}T& operator*(){return *_ptr;}T* operator->(){return _ptr;}//拷贝构造shared_ptr(const shared_ptr& other):_ptr(other._ptr),_pcount(other._pcount){(*_pcount)++;}//赋值shared_ptr& operator=(const shared_ptr& other){//判断自己给自己赋值if (_ptr == other._ptr){return *this;}//处理赋值对象管理的原资源if (*_pcount == 1){delete _ptr;delete _pcount;}else{(*_pcount)--;}//把新资源给赋值对象,同时增加引用计数_ptr = other._ptr;_pcount = other._pcount;++(*_pcount);return *this;}T* get(){return _ptr;}private:T* _ptr;int* _pcount;//用动态资源来管理引用计数,不能用普通类型,因为会导致每个类各自有一个//也不能用静态成员, 因为不能修改};
}

weak_ptr

简介

        weak_ptr是一种弱引用智能指针, 它是为配合 shared_ptr 而引入的,主要用于解决 shared_ptr 可能出现的循环引用问题。他不是RAII智能指针, 他不增加引用计数, 可以访问资源, 不参与资源释放的管理。

实现

        因为weak_ptr不参与资源的管理,所以实现的时候非常简单, 析构函数, 拷贝构造函数和赋值运算符重载都不需要实现, 系统默认生成的就可以使用, 但是除此之外, weak_ptr还要支持用shared_ptr来构造和赋值, 所以我们实现这两个函数:

namespace test
{template<class T>class weak_ptr{public:weak_ptr(T* ptr):_ptr(ptr){}T& operator*(){return *_ptr;}T* operator->(){return _ptr;}//要支持用shared_ptr构造weak_ptr(const shared_ptr<T>& other):_ptr(other._ptr){}//支持用shared_ptr赋值weak_ptr& operator=(const shared_ptr<T>& other){_ptr = other.get();return *this;}private:T* _ptr;};
}

结语

希望这篇关于 C++智能指针 的博客能对大家有所帮助,欢迎大佬们留言或私信与我交流.

学海漫浩浩,我亦苦作舟!关注我,大家一起学习,一起进步!

相关文章推荐

【C++11】左值引用、右值引用、移动语义和完美转发

【C++】STL标准模板库容器set

【C++】模拟实现二叉搜索(排序)树

【C++】模拟实现priority_queue(优先级队列)

【C++】模拟实现queue

【C++】模拟实现stack

【C++】模拟实现list

【C++】模拟实现vector

【C++】标准库类型vector

【C++】模拟实现string类

【C++】标准库类型string

【C++】构建第一个C++类:Date类

【C++】类的六大默认成员函数及其特性(万字详解)

【C++】什么是类与对象?



实际就是把动态开辟的资源交给智能指针来管理.

http://www.dtcms.com/a/512875.html

相关文章:

  • 衡阳市城市建设投资有限公司网站站长之家查询网
  • spark组件-spark core(批处理)-rdd创建
  • 微前端(qiankun)使用教程
  • 婚纱网页制作seo技术306
  • 门户网站特点上海市网站建设公司
  • JS逆向之原型链补环境
  • 广西南宁做网站的公司小榄公司网站建设
  • 一个公司可以注册几个网站wordpress 获取友链
  • 部署大模型的API实战教程!
  • 手机版网站优化html5移动网站开发实例
  • 解释Python中的鸭子类型(Duck Typing)和它与静态类型语言的区别?
  • 数字营销网站建设国外在线crm酒店系统
  • pdw这个conda环境缺少cartopy这个库,将所有依赖下载后使用pip install ./*.whl离线安装,结果报错numpy版本不兼容
  • 用自己的电脑做视频网站微信推广
  • 强化学习2.2 MDP实践——Frozen lake
  • LeetCode 668.乘法表中第k小的数
  • 专业网站建设市场分析自媒体平台哪个收益高
  • 建设通网站怎么样网站如何做响应
  • Java 中的自引用
  • Cursor AI 技术架构、核心模型与技术参数全解析
  • 记录一次线上oom问题排查
  • 深度解析:通过ADO.NET驱动Kdbndp高效连接与操作Kingbase数据库
  • 网站排名怎么上去网站建设捌金手指花总二五
  • 上海做电子商务网站的公司快猫
  • Pycharm远程连接服务器项目
  • linux系统--LVM扩容如何把新的物理卷添加到LVM中 详细教程 超简单
  • 泉州丰泽建设局网站北京做app的公司有哪些
  • 4.8.定义模式
  • Linux命令过关挑战
  • 国内域名购买网站山西省住房和城乡建设厅网站