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

【C++11】智能指针问题


文章目录

  • RAII
  • 一、auto_ptr
  • 二、unique_ptr
  • 三、shared_ptr
    • shared_ptr的循环引用问题
  • 四、weak_ptr
  • 总结



RAII

RAII就是将资源交给一个对象管理,这个对象能进行正常的管理和释放资源。

一、auto_ptr

auto_ptr的问题是:在拷贝构造和赋值重载时,会将自己资源的管理权转移给对方。

template<class T>
class auto_ptr
{
public:auto_ptr(T* ptr):_ptr(ptr){}T& operator*(){return *_ptr;}T* operator->(){return _ptr;}//ap3(ap1)auto_ptr(auto_ptr<T>& ap):_ptr(ap._ptr){ap._ptr = nullptr;//必须置空,否则两个指针对象管理同一块空间,会调用析构两次}operator=(auto_ptr<T>& ap){_ptr = ap._ptr;ap._ptr = nullptr;}~auto_ptr(){delete _ptr; // _ptr是指针,是内置类型,默认生成的析构函数不处理//自定义类型调用它自己的析构_ptr = nullptr;}
private:T* _ptr;
};

这个auto_ptr实际不会用,太挫了。
但面试可能要手撕,也要会。

二、unique_ptr

unique_ptr 简单粗暴地禁止了拷贝和赋值重载,那就解决了上面auto_ptr的管理权转移问题了。

template<class T>class unique_ptr{public:unique_ptr(T* ptr):_ptr(ptr){}T& operator*(){return *_ptr;}T* operator->(){return _ptr;}unique_ptr(unique_ptr<T>& up) = delete;unique_ptr<T>& operator=(unique_ptr<T>& up) = delete;~unique_ptr(){delete _ptr; // _ptr是指针,是内置类型,默认生成的析构函数不处理//自定义类型调用它自己的析构_ptr = nullptr;}private:T* _ptr;};

所以unique_ptr就比较适用于,一个指针独占一个资源的情况。

三、shared_ptr

shared_ptr使用了引用计数器,最开始new对象时,计数器为1。
而当其他的同类型的指针对象也指向该对象时,计数器+1。
当有指针对象调用析构函数时,判断计数器是否为0,如果不为0,表明我这个对象还有其他的shared_ptr在管理,不需要delete,让计数器-1即可。
如果计数器为0,表明当前的shared_ptr是最后一个指针对象管理资源了。就delete。

shared_ptr解决了auto_ptr的管理权转移问题,也解决了unique_ptr的不让拷贝和赋值的问题。

注意的问题:

  • 1.不能赋值给自己,否则计数器会++。
    还有一个问题:默认的析构函数的处理方式是delete ptr。
    如果指针管理的资源是T[],或者是fopen,或者是malloc的呢?
    如果还使用默认的处理方式delete ptr,就会出现问题。
    资源是T[],就得用delete[] ,是fopen,就得用fclose,是malloc,就得用free。
    所以在传参的时候,就需要传处理方法过来了。(可以传对象的方法,可以传lambda,可以传包装器。
    所以就需要将析构函数,设置成一个对象/包装器,调用的就是传进来的析构方法。
  • 2.实现赋值重载的时候,有很多细节。
    • 不能自己给自己赋值
    • 在把对方赋值给自己之前,需要把自己所指向的计时器减减,因为我要只向其他的计时器了。如果减减后的计时器为0,说明这块资源只有我一个指针在管理,现在我要只想其他资源,所以我要先释放我现在的资源才能去指向其他资源,否则就会出现内存泄露问题。
      在这里插入图片描述
template<class T>class shared_ptr{public://1) 使用定制删除器,解决一个当new []时,需要delete []的问题//2) 还有 使用malloc时,需要free配对//3) 使用fopen,需要fclose配对template<class D>shared_ptr(T* ptr,D del):_ptr(ptr),_pcount(new int(1)),_del(del){}//然而这里有一个问题,模板D不是全局的,而是只针对这个构造函数//所以应该如何创建_del对象呢?//使用包装器//function <void(T*)> _del;//因为不管是上面三种情况的哪一种,共同点都是使用的仿函数的返回值都是void,指针类型都是T*T& operator*(){return *_ptr;}T* operator->(){return _ptr;}//sp3(sp1)shared_ptr(shared_ptr<T>& sp):_ptr(sp._ptr),_pcount(sp._pcount) //让他们的引用计数器指针指向同一个计数器{++(*_pcount);}//sp5 = sp2shared_ptr<T>& operator=(shared_ptr<T>& sp){//不能自己赋值给自己,否则引用计数器会++//这样判断是可以的,只要不同的对象指向同一个资源空间,这几个对象之间的赋值都是相当于自己给自己赋值if(_ptr == sp._ptr)  //if (_pcount == sp._pcount) //这也可以{return *this;}//赋值前,需要将之前的计数器--,如果计数器为0,就释放资源//因为我要指向其他资源了,我原来的资源的计数器当然要--if (--(*sp._pcount) == 0){_del(sp._ptr);delete sp._pcount;}_ptr = sp._ptr;_pcount = sp._pcount;++(*_pcount);return *this;}~shared_ptr(){if (--(*_pcount) == 0){_del(_ptr);delete _pcount;_pcount = nullptr;_ptr = nullptr;}}T* get() const {return _ptr;}int use_count() const {return *_pcount;}private:T* _ptr;int* _pcount;//包装器//包装器包装的_del是D类型,这个D也不知道是什么类型,//包装器可以包装仿函数,包装对象的方法等。//如果只是普通的指针析构,那就给一个缺省。function <void(T*)> _del = [](T* ptr) {delete ptr; }; //dzt::shared_ptr<int> svr(new int); //这样的方式,就是没传处理方式,那默认就是用缺省。//dzt::shared_ptr<int> svr(new int[10],[](int* ptr){delete[] ptr};//这样的传参方式,就用delete[]解决};

shared_ptr的循环引用问题

在这里插入图片描述
循环引用问题是两个节点的shared_ptr指针互相指向的时候,引用计数器都会+1,这就出现了互相的计数器都是2.在析构时,都变成1,此时就出现了,到底谁先析构的问题。
就一直死循环了。

不过,shared_ptr能解决日常生活99%的问题,它只有一个缺点,就是循环引用问题。

解决办法:weak_ptr,weak_ptr是专门解决循环引用这个问题的。
weak_ptr没有RAII,没有引用计数,不参与对象资源的管理和释放,只是一个简单的访问资源的操作。

四、weak_ptr

template<class T>class weak_ptr{public:weak_ptr():_ptr(nullptr){}weak_ptr(T* ptr):_ptr(ptr){}//weak_ptr必须支持一个shared_ptr构造weak_ptr的构造函数weak_ptr(const shared_ptr<T>& sp):_ptr(sp.get()){}weak_ptr<T>& operator=(const shared_ptr<T>& sp){//类外面无法直接访问类的私有成员_ptr = sp.get();return *this;}//weak只支持访问资源的操作T& operator*(){return *_ptr;}T* operator->(){return _ptr;}//weak_ptr不参与对象资源的管理和释放,所以没有析构函数private:T* _ptr;};

总结

本文讲述了几个智能指针的优缺点和模拟实现。

相关文章:

【C++11】智能指针问题

文章目录 RAII一、auto_ptr二、unique_ptr三、shared_ptrshared_ptr的循环引用问题 四、weak_ptr总结 RAII RAII就是将资源交给一个对象管理&#xff0c;这个对象能进行正常的管理和释放资源。 一、auto_ptr auto_ptr的问题是&#xff1a;在拷贝构造和赋值重载时&#xff0c…...

借助ChatGPT撰写学术论文,如何设定有效的角色提示词指

大家好&#xff0c;感谢关注。这个给大家提供关于论文写作方面专业的讲解&#xff0c;以及借助ChatGPT等AI工具如何有效辅助的攻略技巧。有兴趣的朋友可以添加我&#xff08;yida985&#xff09;交流学术写作或ChatGPT等AI领域相关问题&#xff0c;多多交流&#xff0c;相互成就…...

成功在服务器liunx-ubantu上安装pytorch

sudo pip3 install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118参考链接&#xff1a; 教程&#xff08;部分参考&#xff09; Pytorch官网...

【面试干货】抽象类和接口的区别

【面试干货】抽象类和接口的区别 1、抽象类1.1、什么是抽象类&#xff1f;1.2、示例代码 2、接口2.1、什么是接口&#xff1f;2.2、示例代码 3、比较和总结3.1、使用场景3.2、关键区别3.3、代码示例比较 &#x1f496;The Begin&#x1f496;点点关注&#xff0c;收藏不迷路&am…...

python爬虫:实现动态网页的爬取,以爬取视频为例

引言: 爬虫也被称为网络蜘蛛(Spider),是一种自动化的软件程序,能够在互联网上漫游,按照一定的规则和算法抓取数据。 爬虫技术广泛应用于搜索引擎、 数据挖掘 、信息提取等领域,是互联网技术的重要组成部分。 摘要: 作为爬虫的初学者,网页越简单越好,因为网页的结构…...

Incredibuild for Mac 来了!

Mac 开发者在寻找适合自己需求的工具时可能会遇到一些困难&#xff0c;因为 Mac 操作系统相对封闭&#xff0c;不像其他系统那样开放和灵活。尽管如此&#xff0c;Mac 开发者在开发应用程序时的需求&#xff08;比如功能、效率等&#xff09;和使用其他操作系统的开发者是类似的…...

递归解析 LXML 树并避免重复进入某个节点

1、问题背景 我们在使用 LXML 库解析 MathML 表达式时&#xff0c;可能会遇到这样一个问题&#xff1a;在递归解析过程中&#xff0c;我们可能会重复进入同一个节点&#xff0c;导致解析结果不正确。例如&#xff0c;我们希望将以下 MathML 表达式解析为 Python 表达式&#x…...

GaussDB技术解读——GaussDB架构介绍(三)

目录 9 智能关键技术方案 智能关键技术一&#xff1a;自治运维系统 智能关键技术二&#xff1a;库内AI引擎 智能关键技术三&#xff1a;智能优化器 10 驱动接口关键技术方案 GaussDB架构介绍&#xff08;二&#xff09;从数据持久化存取层(DataNode)关键技术方案、全局事…...

解锁ChatGPT:从原理探索到GPT-2的中文实践及性能优化

⭐️我叫忆_恒心&#xff0c;一名喜欢书写博客的研究生&#x1f468;‍&#x1f393;。 如果觉得本文能帮到您&#xff0c;麻烦点个赞&#x1f44d;呗&#xff01; 近期会不断在专栏里进行更新讲解博客~~~ 有什么问题的小伙伴 欢迎留言提问欧&#xff0c;喜欢的小伙伴给个三连支…...

【WPF】中的ListBox的ScrollIntoView方法使用

在WPF中&#xff0c;ListBox控件的ScrollIntoView方法用于确保指定的项在可视区域内可见。如果该项不在当前的视图中&#xff0c;该方法会滚动列表&#xff0c;使该项出现在视图中。这对于在用户交互或程序逻辑中需要突出显示特定列表项的场景非常有用。但是不会指定滚动的对齐…...

信息安全等级保护测评(等保测评)定级的重要性与实施路径

#等保测评##黑龙江等保测评##哈尔滨等保测评# 在数字化转型的浪潮中&#xff0c;信息安全已成为保障国家安全、社会稳定及企业发展的基石。信息安全等级保护测评&#xff08;简称“等保测评”&#xff09;&#xff0c;作为中国网络安全领域的基础性制度&#xff0c;为组织机构的…...

Python库

Python库 babel huey 图片视频处理 moviepy 一个用于视频编辑的Python模块,可用于进行视频的基本操作(如剪切、连接、标题插入)、视频合成(也称非线性编辑)、视频处理或创建高级效果 patchworklib 一个专注于图像拼接和合成的Python库 patchworklib 一个专注与图…...

pytest+requests+allure自动化测试接入Jenkins学习

&#x1f345; 视频学习&#xff1a;文末有免费的配套视频可观看 &#x1f345; 点击文末小卡片 &#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 最近在这整理知识&#xff0c;发现在pytest的知识文档缺少系统性&#xff0c;这里整理一下&…...

你能不能手敲出Spring框架?

Spring最成功的地方在于创始人Rod Johnson提出的IOC、AOP核心理念&#xff0c;反而不是其本身的技术。技术上今天可以有Spring春天&#xff0c;明天就可以有Autumn秋天。 核心理念有多重要&#xff1f;就如1871年巴黎公社的失败。公社在对抗法国zf和普鲁士占领军的背景下成立&…...

实体店如何通过私域获取流量?

随着互联网的快速发展和消费者购物习惯的变化&#xff0c;私域流量对于实体店的重要性日益凸显。私域流量是指企业在自己的平台上沉淀的、可以免费使用、多次利用的流量&#xff0c;如微信生态下的朋友圈、公众号、企业微信等。对于实体店而言&#xff0c;有效利用私域流量不仅…...

互联网与人工智能时代:问题的新形态与解答的挑战

随着互联网的普及和人工智能技术的飞速发展&#xff0c;我们仿佛进入了一个答案触手可及的新时代。然而&#xff0c;就在我们以为问题将因此逐渐减少之时&#xff0c;实则问题的形态和内涵正在发生深刻的变化。因此&#xff0c;我们不应简单地将互联网和人工智能视为解决问题的…...

机器学习与数据挖掘知识点总结(二)分类算法

目录 1、什么是数据挖掘 2、为什么要有数据挖掘 3、数据挖掘用在分类任务中的算法 朴素贝叶斯算法 svm支持向量机算法 PCA主成分分析算法 k-means算法 决策树 1、什么是数据挖掘 数据挖掘是从大量数据中发现隐藏在其中的模式、关系和规律的过程。它利用统计学、机器学…...

MySQL数据库初体验

目录 1.数据库基本概念 1.1 数据Data 1.2 表 1.3 数据库 1.4 数据库管理系统(DBMS) 1.5 数据库系统&#xff08;DBS&#xff09; 2.数据库的发展 3.主流的数据库介绍 3.1 SQL Server&#xff08;微软公司产品&#xff09; 3.2 Oracle &#xff08;甲骨文公司产品&…...

关于RDMA传输的基本流量控制

Basic flow control for RDMA transfers | The Geek in the Corner (wordpress.com) 名词解释 IB &#xff1a; InfiniBand的缩写&#xff0c;指的就是InfiniBand技术。 MAD &#xff1a; Management Datagram的缩写。MAD是InfiniBand架构中用于设备管理和配置的一种特殊消息…...

Android Studio新增功能:Device Streaming

今天将Android Studio升级到2023.3.1 Patch2。发现新增了Device Streaming功能。支持远程使用Google的物理设备调试程序。这样可以方便地在真实设备上测试自己的APP。这对于手头没有Google设备的开发者而言&#xff0c;确实方便很多。该功能目前处于测试阶段&#xff0c;在2025…...

从理论到实践:百川2-13B模型权重加载与推理过程代码解读

从理论到实践&#xff1a;百川2-13B模型权重加载与推理过程代码解读 你是不是也遇到过这种情况&#xff1a;好不容易找到一个开源大模型&#xff0c;比如百川2-13B&#xff0c;兴冲冲地下载下来&#xff0c;结果面对那一堆模型权重文件和复杂的代码&#xff0c;瞬间就懵了&…...

让屏幕标注像在纸上写字一样自然:gInk 三分钟上手指南

让屏幕标注像在纸上写字一样自然&#xff1a;gInk 三分钟上手指南 【免费下载链接】gInk An easy to use on-screen annotation software inspired by Epic Pen. 项目地址: https://gitcode.com/gh_mirrors/gi/gInk 你是否曾经在线上会议中&#xff0c;想快速圈出PPT的重…...

Multisim新手必看:用差分放大电路课设,手把手教你搞定仿真与波形分析

Multisim新手必看&#xff1a;用差分放大电路课设&#xff0c;手把手教你搞定仿真与波形分析 第一次打开Multisim时&#xff0c;满屏的元器件和复杂的参数设置确实容易让人望而生畏。记得我大三做模电课设时&#xff0c;光是找齐差分放大电路需要的元件就花了半小时&#xff0c…...

解锁5大核心技术:MelonLoader模组加载器完全指南

解锁5大核心技术&#xff1a;MelonLoader模组加载器完全指南 【免费下载链接】MelonLoader The Worlds First Universal Mod Loader for Unity Games compatible with both Il2Cpp and Mono 项目地址: https://gitcode.com/gh_mirrors/me/MelonLoader 引言&#xff1a;U…...

SenseVoice WebUI镜像体验:上传音频秒获文字+表情标签,小白也能玩转

SenseVoice WebUI镜像体验&#xff1a;上传音频秒获文字表情标签&#xff0c;小白也能玩转 1. 快速了解SenseVoice WebUI SenseVoice WebUI是一个开箱即用的语音识别工具&#xff0c;它能将你上传的音频文件快速转换成文字&#xff0c;并自动标注说话人的情感状态和音频中的特…...

千问3.5-2B参数详解教程:max_new_tokens=192与temperature=0.7如何影响图文理解质量

千问3.5-2B参数详解教程&#xff1a;max_new_tokens192与temperature0.7如何影响图文理解质量 1. 认识千问3.5-2B视觉语言模型 千问3.5-2B是Qwen系列中的小型视觉语言模型&#xff0c;它能够同时理解图片内容和生成文本回答。这个模型特别适合需要结合视觉和语言理解的任务场…...

HunyuanVideo-Foley效果评测:与AudioLDM、MERT等主流音效模型横向对比

HunyuanVideo-Foley效果评测&#xff1a;与AudioLDM、MERT等主流音效模型横向对比 1. 评测背景与测试环境 1.1 评测目标 本次评测旨在对比HunyuanVideo-Foley与当前主流音效生成模型&#xff08;AudioLDM、MERT&#xff09;在音效质量、生成速度、资源占用等方面的表现。测试…...

零代码!用Qwen-Image-2512-ComfyUI轻松制作中文电商配图与营销素材

零代码&#xff01;用Qwen-Image-2512-ComfyUI轻松制作中文电商配图与营销素材 1. 为什么选择Qwen-Image-2512-ComfyUI 电商运营和内容创作者经常面临一个共同难题&#xff1a;如何快速制作高质量的中文营销素材。传统设计工具需要专业技能&#xff0c;而普通AI绘画工具又难以…...

从MATLAB到C++:手把手教你将鱼眼相机标定结果(Scaramuzza模型)部署到OpenCV项目

从MATLAB到C&#xff1a;手把手教你将鱼眼相机标定结果&#xff08;Scaramuzza模型&#xff09;部署到OpenCV项目 鱼眼相机因其超广视角在机器人导航、虚拟现实等领域应用广泛。但MATLAB标定结果如何无缝迁移到C工程环境&#xff1f;本文将彻底解决这个痛点&#xff0c;带您完成…...

JDK 17 + Spring Boot 3.5.8:企业级开发技术栈全景分析

JDK 17与Spring Boot 3.5.8的核心特性JDK 17 LTS特性 JDK 17作为长期支持版本&#xff08;LTS&#xff09;&#xff0c;提供多项生产级增强&#xff1a;密封类&#xff08;Sealed Classes&#xff09;&#xff1a;通过sealed和permits关键字限制类的继承关系&#xff0c;增强领…...