首页 > 其他分享 >智能指针学习

智能指针学习

时间:2023-05-20 22:23:06浏览次数:29  
标签:学习 智能 计数器 析构 shared 拷贝 ptr 指针

c++的抛异常解决了返回错误码与函数层层返回的问题,但是异常往往可能有很多种,也有可能前面开辟了很多个空间,之后随着抛异常,这些空间都等着释放,这就太麻烦了,有可能会在写代码的时候疏忽忘记了释放这块空间造成内存泄漏,

所以智能指针可以很好的处理这种情况,我们知道c++中的类可以在其生命周期结束时自动调用他的析构函数,不如用一个自定义类去封装这个指针让其在出了作用域过后自己析构自己,然后这个类来充当指针的作用,重载解引用运算符和指针运算符,这样就解决了人力无法顾及到一些指针释放的问题了.

需要注意的是智能指针不可以去拷贝构造,和使用深拷贝运算符,因为这个类是代理管理这个指针,如果拷贝出来一个另外的指针,这算什么?,算弄出来一个没用的空间?也不可以浅拷贝,这关乎到哪一个指针有析构的权利这个问题,开辟空间的地址只有一份,若是有很多个地方都在用这个智能指针,一个析构了就全崩了.

所以为了解决这个问题有了

auto_ptr:他是通过转移拷贝来解决这个问题的,当拷贝构造或者赋值运算符时,将自身的空间交给另一个,自己空间置为空,就防止了多个智能指针指向同一个空间的问题了.但是这样原来的指针为空万一访问了就坏了,所以又有了unique_ptr.

unique_ptr:这个智能指针会更加直接,他直接将拷贝构造私有化并用delete修饰,这样就不会有人调用拷贝构造的风险了.但是如果非要拷贝怎么办呢.又有了shared_ptr.

shared_ptr:以上废了好大功夫禁止使用拷贝构造归根结底就是防止指针在不该析构的时候被析构,于是shared_ptr用了一个指针变量作为成员便利那个来记录这个指针有多少个对象在使用,他只在有参或无参构造时开辟空间,拷贝构造时就给这个计数器加一,析构时判断这个计数器,是否为零,如果为零就释放空间,如果不为零就计数器减一,这样就可以同时存在多个指向一个指针的智能指针了。

在编程中往往可能会遇到多线程编程的问题:这个shared_ptr在一个线程中运行时没问题,若是在多线程中使用,就会出现线程安全问题,因为这个计数器的加一并不是原子指令,他有可能被多个线程同时访问,导致计算不准确,这时就需要上锁了:用锁将计数器的计算过程锁起来后,shared_ptr就线程安全了。

 这里将这个锁放在成员变量里,用的时候更加方便。

上面的share_ptr看着已经完善了,但是在使用的过程中发现还是有缺陷,比如循环引用问题》

此时我需要自定义一个双向链表,因为种种原因链表的指针需要是智能指针,因此结点中的两个指针域也应该为智能指针,为了同种类型相互兼容,当初始化两个节点后此时两个个智能指针的计数器都为一,但是当两个结点相互连接后,因为赋值运算符的浅拷贝,是各自的计数器都变成了2,这是如果析构第一个结点,和第二个节点他们析构完了结点各自减少了一次,此时析构完成但是计数器并没有归零,所以空间没有释放,又出现问题了。

这时有有了weak_ptr,他的功能就是让两个shared_ptr指针进行浅拷贝但是不增加计数器,他的构造函数参数可以是一个share_ptr,通过传入一个shared_ptr,让他指向这个shared_ptr代理的指针,完成拷贝,这其中需要解决访问权限问题,因为weak无法访问shared的私有成员变量。

所以可以将双向链表的指针域换成weak_ptr类型就可以连接上同时不增加shared的计数器。这样就解决了循环引用的问题。

但是平时再开辟空间时并不只是开辟一个空间有时会开辟一段连续的空间,这又怎么办呢?用delete释放delete【】会出问题的

可以用把智能指针的析构函数作为模板参数,在外面实现,因为释放数组与释放一个空间不同的地方在于析构函数的不同。这是不仅可以处理delete也可以处理delete[],mallic和文件指针。

 

标签:学习,智能,计数器,析构,shared,拷贝,ptr,指针
From: https://www.cnblogs.com/qjwxlj/p/17417911.html

相关文章

  • 算法学习笔记合集
    字符串哈希:哈希学习笔记KMP:KMP学习笔记图论分层图最短路:分层图最短路LCA:P3379最近公共祖先模板数据结构线段树:线段树学习笔记ST表:P3865ST表树状数组:P3374树状数组1DP树上背包:P2014选课(树上背包)杂项搜索:搜索学习笔记离散化:离散化学习笔记......
  • C初级指针复习
    C初级指针复习:内存:内存中的每一个位置都由一个独一无二的地址标识每一个内存位置都包含一个值值和类型:不能简单地通过检查一个值的位来判断它的类型,为了判断值的类型(以及它的值),必须观察程序中这个值的使用方式,值的类型并非值本身所固有的一种特性,而是取决于它的使用方式NULL......
  • ABBAC900F学习笔记301:使用securityLock做解除联锁按钮的权限限制功能
    这一篇学习笔记,我在新浪博客记录过,因为担心丢失,在这里再记录一遍,新浪博客地址ABBAC900F学习笔记301:使用securityLock做解除联锁按钮的权限限制功能_来自金沙江的小鱼_新浪博客(sina.com.cn) 这个学习练习,实际上还是在以前学习基础上做的,没有多少新意,权当复习一遍吧。在虚拟......
  • Python学习
    3-13字符串类型字符串类型:str   1.定义格式:       变量='内容'           打印一行       变量="内容"           打印一行       变量='''内容'''或者三引号           可以通过回车的方式换行,且打印出......
  • Python学习
    3-13字符串类型字符串类型:str   1.定义格式:       变量='内容'           打印一行       变量="内容"           打印一行       变量='''内容'''或者三引号           可以通过回车的方式换行,......
  • 【学习笔记】(8) 拉格朗日插值
    拉格朗日插值首先一个定理:\(n\)个点(横坐标不同)唯一确定一个最高\(n-1\)次的多项式。那么,\(n\)个点的点值\((x_i,y_i)\)可以唯一确定一个\(n−1\)次多项式(为了叙述方便,本文中所有“\(k\)次多项式”“\(k\)次函数”的最高次项系数可以为0)。拉格朗日插值就是用......
  • 初等数论学习笔记
    线性筛素数直接上代码。constintMAXN=100000008;boolnp[MAXN];vector<int>prm,pre;voidgg(constintN=100000000){ pre.resize(N+1); for(inti=2;i<=N;i++){ if(np[i]==false){ prm.push_back(i); pre[i]=i; } for(autoj:prm)if(i*j<=N){ int......
  • 【学习笔记】(1) 差分约束
    1.算法介绍差分约束系统是一种特殊的\(N\)元一次不等式组,它包含\(N\)个变量\(X_1\simX_N\)以及\(M\)个约束条件,每个约束条件是由两个其中的变量做差构成的,形如\(X_i-X_j\lec_k\),其中\(1\lei,j\leN,1\lek\leN\)并且\(c_k\)是常数(可以是非负数,也可以......
  • 学习Javaweb中遇到的数据回显显示问题
    问题描述:当点击修改按钮时,显示的内容如下:解决方案:加上isELIgnored="false"<%@pagecontentType="text/html;charset=UTF-8"language="java"isELIgnored="false"%>最终结果显示:......
  • 算法学习day25回溯part02-216、17
    packageLeetCode.backtrackpart02;importjava.util.ArrayList;importjava.util.LinkedList;importjava.util.List;/***216.组合总和III*找出所有相加之和为n的k个数的组合,且满足下列条件:*只使用数字1到9*每个数字最多使用一次*返回所有可能的有效......