程序员成长之旅——智能指针

  • 智能指针的发展旅程
  • 智能指针的模拟实现
  • 智能指针常见的问题个人理解

智能指针的发展旅程

我所了解的智能指针其实是为了解决一些异常安全的问题的,它是运用RAII思想封装的类,从而可以达到自动析构的形式。

auto_ptr
C++98提出来的第一个智能指针,它是一个类似管理权转让的形式,拷贝构造或者赋值的时候,将其原本的管理权转交给新的对象。
unique_ptr
C++11提出来的,它的特性非常的明确,就是防拷贝和赋值,将其私有化,或者delete。
shared_ptr
C++11提出来的,这是为了可以支持拷贝和赋值出现的,它的底层其实是用引用计数来实现的。
weak_ptr
这边这个C++11提出来的主要是为了弥补shared_ptr的缺点,有循环引用的可能,因此是用它来解决的。

智能指针的模拟实现

auto_ptr

template<class T>class auto_ptr {public:auto_ptr(T* ptr = nullptr) :_ptr(ptr){}auto_ptr(const auto_ptr<T>& tmp){_ptr = tmp._ptr;tmp._ptr = nullptr;}auto_ptr<T>& operator=(const auto_ptr<T>& tmp){if (_ptr != tmp._ptr){if(_ptr)delete(_ptr);_ptr = tmp._ptr;tmp._ptr = nullptr;}return *this;}~auto_ptr(){if (_ptr)delete(_ptr);}T& operator*(){return *_ptr;}T* operator->(){return _ptr;}private:T* _ptr;};

从上面我们可以看到,运用auto_ptr的话,在将管理权转让出去之后,如果我们在使用原对象,就会出现错误,为了避免这种错误,C++11提出了更优的智能指针。
unique_ptr

template<class T>class unique_ptr{public:unique_ptr(T* ptr = nullptr):_ptr(ptr){}~unique_ptr(){if (_ptr)delete(_ptr);}T& operator*(){return *_ptr;}T* operator->(){return _ptr;}//C++11的用法unique_ptr(const unique_ptr<T>&) = delete;unique_ptr<T>& operator=(const unique_ptr<T>&) = delete;private:T* _ptr;};

shared_ptr

     template<class T>class shared_ptr{public:shared_ptr(T* ptr = nullptr):_ptr(ptr),_pCount(new int(1)),_mtu(new mutex){}shared_ptr(const shared_ptr<T>& tmp):_ptr(tmp._ptr),_pCount(tmp._pCount),_mtu(tmp._mtu){AddRef();}shared_ptr<T>& operator=(const shared_ptr<T>& tmp){if (_ptr != tmp._ptr){Release();_ptr = tmp._ptr;_pCount = tmp._pCount;AddRef();}return *this;}T& operator*(){return *_ptr;}T* operator->(){return _ptr;}~shared_ptr(){Release();}private:void AddRef(){_mtu->lock();++(*_pCount);_mtu->unlock();}void Release(){bool flag = false;_mtu->lock();if (--(*_pCount) == 0){delete(_pCount);delete(_ptr);flag = true;}_mtu->unlock();if (flag == true)delete(_mtu);}T* _ptr;int* _pCount;mutex* _mtu;};

以上就是shared_ptr的简单模拟实现,它所存在的最大问题就是,它会有循环引用的问题。举个例子:

typedef struct ListNode{shared_ptr<ListNode> _next;shared_ptr<ListNode> _prev;int _val;}ListNode;void Test(){shared_ptr<ListNode> t1(new ListNode);shared_ptr<ListNode> t2(new ListNode);t1->_next = t2;t2->_prev = t1;}

画个图就理解为何出现循环引用了

而为了解决这个情况,我们就引入了弱指针,来解决这个问题。
weak_ptr

 template<class T>class weak_ptr{public:weak_ptr():_ptr(nullptr){}weak_ptr(const shared_ptr<T>& tmp){_ptr = tmp.GetPtr();}weak_ptr<T>& operator=(const shared_ptr<T>& tmp){_ptr = tmp.GetPtr();return *this;}private:T* _ptr;};struct ListNode{//我们将会发生循环引用的指针用弱指针来完成它weak_ptr<ListNode> _next;weak_ptr<ListNode> _prev;int _val;};void Test(){shared_ptr<ListNode> t1(new ListNode);shared_ptr<ListNode> t2(new ListNode);t1->_next = t2;t2->_prev = t1;}

简单的来说,weak_ptr就是只要能构成循环引用的,我们都不将它进行计数加加,这样的话就能有效解除掉循环引用的问题了。

智能指针常见的问题个人理解

1.模拟实现shared_ptr的时候,引用计数是放在栈上还是堆上,说其中原因?
是在堆上
我认为不放在栈上的理由很简单,就是为了手控这个释放内存的时刻,不会让编译器自动控制,这样子的话,就可能会造成,多个对象指向同一个控制块,当某一个对象作用域 结束的时候,栈上面的这个引用计数就会释放,其它的在使用就会出错。

2.模拟shared_ptr的时候为何在计数++和–的时候要加锁?
会有线程安全的问题
因为++和–是非原子操作的,因此会出现多个线程争抢访问,从而出现线程安全的问题,因此要将其加锁,保证其原子性操作。

补充一个小知识点:+ +为何不是线程安全的
拿++来说的话,它的内部执行至少有三个指令
从内核读取数据
将数据读取到寄存器+1
将寄存器数据写入到内核

并且这三个指令是独立运行的,它们单方面都是原子操作的,但是在多线程并发的情况下,如果两个操作及两个操作以上是一体的话,就是非原子操作,也就是引发线程安全问题的真正缘由。
以上有任何问题,欢迎指正

程序员成长之旅——智能指针相关推荐

  1. 程序员成长之旅——同步IO和异步IO(五种IO模型)

    程序员成长之旅--同步IO和异步IO(五种IO模型) 同步和异步 同步 异步 消息通知 场景比喻 阻塞和非阻塞 阻塞 非阻塞 事例 同步IO 阻塞IO 非阻塞IO 信号驱动IO 多路转接IO 异步IO ...

  2. 程序员成长之旅——C语言三子棋

    程序员成长之旅--C语言三子棋 简易介绍三子棋 三子棋编程过程 三子棋代码总览 game.h game.c test.c 简易介绍三子棋 进行了这么多天的c语言学习,今天给大家讲一下三子棋是如何用c语 ...

  3. 程序员成长之旅——Delphi实现一个简单的科学计算器

    程序员成长之旅--Delphi实现一个简单的科学计算器 目标效果 组件以及开发环境 最终呈现 源码GITHUB 目标效果 组件以及开发环境 delphi7版本及以上,这里我用delphi10.4进行的 ...

  4. 程序员成长的本质,就是一步步靠近商业

    职业规划与职业发展是每个程序员经常要考虑的一个问题,每年的晋升,述职,甚至于跳槽都是需要去想的一个问题.那么程序员成长到后期,其成长的本质是什么呢?慢慢得出了一个结论,就是一步步靠近商业. 我之前想过 ...

  5. 典型的 C++ 程序员成长经历

    From:http://blog.csdn.net/breakerzy/article/details/7399872 一个典型的 C++ 程序员成长经历: 1.  完整的学一遍 C++ 所有语言特性 ...

  6. 程序员成长的10个阶段

    我的程序员成长之路 程序员的成长经历往往很相似,大部分的人走过了最前面相同的一段路,而有的人则走得更远.总结自己这些年来的历程,这也许能让年轻的程序员少走一些弯路,成长得更快:或许更好一些,能让大家从 ...

  7. 程序员成长之路--软件架构

    程序员成长之路--软件架构 一.想成为一个合格的架构师,你要知道软件架构是个什么概念,明白架构的定义: 1.软件架构是一个系统的草图. 2.软件架构描述的对象是直接构成系统的抽象组件. 3.各个组件之 ...

  8. 原来程序员成长的关键竟然是它?!

    就目前的IT大环境而言,程序员的日子不是很好过,无论是正在找工作的还是已经入职的,压力都非常大,似乎处处充满危机.但是究其原因,他们之间大部分都缺乏同一种东西--项目经验.没错,在我看来,项目经验就是 ...

  9. 原创电子书《菜鸟程序员成长之路:从技术小白到阿里巴巴Java工程师》

    <菜鸟程序员成长之路:从技术小白到阿里巴巴Java工程师> 国庆节快乐!一年一度长度排第二的假期终于来了. 难得有十一长假,作者也想要休息几天啦. 不管你是选择出门玩,还是在公司加班,在学 ...

最新文章

  1. 定时清理日志文件-python实现
  2. 听说你开发.NET还在用VS,小哥哥给你推荐全平台的Rider
  3. OpenCL向量相加
  4. 最短路径和距离及可视化——matlab
  5. lucene 搜索学习笔记 - OK
  6. 【火灾检测】基于matlab GUI火灾检测(带面板)【含Matlab源码 1646期】
  7. 企业微信管理员可以看到打卡位置吗
  8. 仿360悬浮窗——进阶篇
  9. 【STM32-V7】STM32H743XIH6开发板,丰富软件资源,强劲硬件配置,大量软件解决方案持续更新中(2022-11-22)
  10. 从Watson看AI平台的架构设计
  11. AE开发中鹰眼的隐藏
  12. cdn刷新api_缓存刷新与查询
  13. AI First:互联网进步的背后,反映出的是流量的再分配
  14. 2007年IT产业回顾:划时代的一年 一个变革的时代
  15. 管家婆设置软件登录限制
  16. 电机控制反Park变换和反Clarke变换公式推导
  17. 表格中复制粘贴到其他位置的数据会携带引号等不可见字符
  18. 2020年南大计算机、软件工程考研经验分享
  19. 八个移动产品设计必备网站
  20. 财务自由之路——为什么选择淘宝(上)

热门文章

  1. Springboot实现简单登录
  2. 新入手17款MacbookPro15寸
  3. 中国澳门sinox很多平台CAD制图、PCB电路板、IC我知道了、HDL硬件描述语言叙述、电路仿真和设计软件,元素分析表...
  4. 分销级差奖励制度实现思路
  5. 如何建立有效的项目管理制度?
  6. android 高德地图 3d,在React Native中使用 高德地图组件react-native-amap3d
  7. Kinect C++简单切水果的一点总结
  8. llt自发光_Luminox 全新「SR-71 Blackbird」黑色限量版腕表
  9. 为什么106短信那么火?
  10. MIT 6.828 (二) Lab 2: Memory management