C++智能指针


一、智能指针的作用

上一篇介绍了内存池的原理和实现,详情请见内存池设计与实现;

内存池可以帮助我们有效的对内存进行管理,智能指针可以很方便的管理指针,避免出现内存泄漏;

智能指针的作用

智能指针的作用:智能指针可以帮助我们避免在申请空间后忘记释放造成内存泄漏的问题;因为智能指针本身是一个类(后面也会自己实现一下),当出了类的作用域的时候,类会调用析构函数进行释放资源。所以智能指针的作用原理就是在函数结束时自动释放内存空间,不需要手动释放内存空间。


二、智能指针的原理

我们这里的指针指针主要指的是shared_ptr,这也是一种引用计数型智能指针,引用计数顾名思义就是在内存中记录有多少个智能指针被引用,新增一个引用计数加一,过期引用计数则减一,当引用计数为0的时候,

智能指针才会释放资源;

案例一

#include #include 

using namespace std;

class A{public: A() {  cout <"A Constructor" <endl; } ~A() {  cout <"A Destruct" <endl; }};

int main(){ shared_ptr p = make_shared();cout <"count:"<endl;return 0;}

结果:

root@iZuf67on1pthsuih96udyfZ:~/C++/Net_C++/demo4# ./test1 A Constructorcount:1A Destruct

我们再增加一个传参,看一下引用计数:

案例二

#include #include 

using namespace std;

class A{public: A() {  cout <"A Constructor" <endl; } ~A() {  cout <"A Destruct" <endl; }};

void fun(shared_ptrp){       cout<<"fun count:"<endl;}int main(){shared_ptr p = make_shared();cout <"count:"<endl;    fun(p);cout <"count:"<endl;return 0;}

结果:

root@iZuf67on1pthsuih96udyfZ:~/C++/Net_C++/demo4# ./test1 A Constructorcount:1fun count:2count:1A Destruct

通过上面的两个例子,我们验证了最开始说的:智能指针本身是一个类(后面也会自己实现一下),当出了类的作用域的时候,类会调用析构函数进行释放资源;


三、智能指针的使用

智能指针的使用比较简单,在我们程序中需要包含头文件:

#include 

注意:智能指针是C++11 的标准,在编译的时候需要加上 -std=c++11 的编译参数;

使用智能指针初始化有几种方式,newmake_shared,这里推荐使用make_shared,原因是:make_shared标准库函数,是最安全的分配和使用动态内存的方法,此函数在动态内存中分配一个对象并初始化它,返回指向此对象的shared_ptr;头文件和share_ptr相同。

简单给个案例:

案例三

#include #include 

using namespace std;

class A{public:    A(int count)    {        _nCount = count;    }    ~A(){}    void Print(){        cout<<"count:"<<_ncount>endl;    }private:int _nCount;};int main(){   shared_ptrp = make_shared(10);    p->Print();return 0;}

编译过程;

root@iZuf67on1pthsuih96udyfZ:~/C++/Net_C++/demo4# g++ -std=c++11 test2.cpp -o test2root@iZuf67on1pthsuih96udyfZ:~/C++/Net_C++/demo4# ./test2count:10

四、智能指针使用注意项

我们先来看一段代码:

案例四

#include #include 

using namespace std;

class B;

class A{public:    shared_ptr_pb;};class B{public:shared_ptr_pa;};int main(){shared_ptrpa = make_shared();shared_ptrpb = make_shared();cout<<"pa count:"<endl;cout<<"pb count:"<endl;    pa->_pb = pb;    pb->_pa = pa;cout<<"pa count:"<endl;cout<<"pb count:"<endl;return 0;}

结果;

root@iZuf67on1pthsuih96udyfZ:~/C++/Net_C++/demo4# g++ -std=c++11 test3.cpp -o test3root@iZuf67on1pthsuih96udyfZ:~/C++/Net_C++/demo4# ./test3pa count:1pb count:1pa count:2pb count:2

会发现,最终的引用计数为2,那么结束后,引用计数不为0,他们在堆上的空间不会被释放,这就是常说的循环引用

当然,这不是无解的,我们可以另外一种只能指针,只不过这是种弱指针---weak_ptr,这种指针不会增加引用计数,配合shared_ptr,可谓是郎才女貌,皆大欢喜呀!

案例五

#include #include 

using namespace std;

class B;

class A{public:    weak_ptr_pb;};class B{public:    weak_ptr_pa;};int main(){shared_ptrpa = make_shared();shared_ptrpb = make_shared();cout<<"pa count:"<endl;cout<<"pb count:"<endl;    pa->_pb = pb;    pb->_pa = pa;cout<<"pa count:"<endl;cout<<"pb count:"<endl;return 0;}

结果:

root@iZuf67on1pthsuih96udyfZ:~/C++/Net_C++/demo4# g++ -std=c++11 test3.cpp -o test3root@iZuf67on1pthsuih96udyfZ:~/C++/Net_C++/demo4# ./test3pa count:1pb count:1pa count:1pb count:1

很清晰的发现,在最后互相引用的时候,引用计数器没有加一,最后出作用域的时候就会调用析构函数,进行内存释放;


五、智能指针的实现

实现智能指针,无论是在面试还是深刻理解智能指针方面,对我们帮助都是非常大的,理解了上面的原理,我们动手实现一个智能指针:

智能指针实现代码

#include 

using namespace std;

template<class T>class SmartPoint{public: //构造函数 SmartPoint(T* p=NULL) {  _ptr = p;  if (p != NULL)  {   _count = 1;  }  else  {   _count = 0;  } } //析构函数 ~SmartPoint() {  if (--_count == 0)  {   delete _ptr;  } } //拷贝构造函数 SmartPoint(const SmartPoint& src) {  if (this != &src)  {   _ptr = src._ptr;   _count = src._count;   _count++;  } }

 //重载赋值操作符 SmartPoint& operator=(const SmartPoint& src) {  if (_ptr == src._ptr)  {   return *this;  }  if (_ptr)  {   _count--;   if (_count == 0)   {    delete _ptr;   }  }  _ptr = src._ptr;  _count = src._count;  _count++;  return *this; }

 //重载操作符 T* operator ->() {  if (_ptr)   return _ptr; }

 //重载操作符 T& operator *() {  if (_ptr)   return *_ptr; }

 size_t use_count() {  return _count; }private: T* _ptr; size_t _count;

};

void Use(SmartPoint<char> p){ int n = p.use_count();}

int main(){ SmartPoint<char>sp1(new char); Use(sp1); SmartPoint<char>sp2(sp1); SmartPoint<char>sp3; sp3 = sp1; int n = sp1.use_count(); return 0;}

往期精彩文章推荐

  • 内存池设计与实现
  • 恭喜你!发现宝藏一份--技术文章汇总
  • C++11 计时器!真香
  • 我们需要懂得CMake文件

想了解学习更多C++后台服务器方面的知识,请关注:微信公众号:====**CPP后台服务器开发**====


扫码CPP后台服务器开发转载是一种动力 分享是一种美德

智能指针的释放_看完这篇,别再说不会智能指针了相关推荐

  1. redis hashmap过期_看完这篇再也不怕 Redis 面试了

    0.前言 Redis是跨语言的共同技术点,无论是Java还是C++都会问到,所以是个高频面试点. 笔者是2017年才开始接触Redis的,期间自己搭过单机版和集群版,不过现在 大一些的 公司都完全是运 ...

  2. 苹果地图副总裁_看完这篇文章 或许你会再给“苹果地图”一次机会

    地图 4 岁了. 苹果负责互联网服务和软件的高管 Eddy Cue 和 Craig Federighi,受访畅谈地图业务"得失"的机会并不多.采访实录还没看完,我抓起 iPhone ...

  3. python泰勒公式法求正弦函数_看完这篇让你高数不挂科之——泰勒公式

    本文始发于个人公众号:TechFlow,原创不易,求个关注 今天的文章我们来讨论大名鼎鼎的泰勒公式,泰勒公式真的非常有名,我相信上过高数课的一定都记得它的大名.即使你翘掉了所有的课,也一定会在考前重点 ...

  4. excel正在等待某个应用程序以完成对象链接与嵌入操作_看完这篇操作系统,和面试官扯皮就没问题了

    各位看官内容喜欢的话,动动手指点个 ,点个关注呗!!谢谢支持! 解释一下什么是操作系统 操作系统是运行在计算机上最重要的一种软件,它管理计算机的资源和进程以及所有的硬件和软件.它为计算机硬件和软件提供 ...

  5. 为什么子进程每次执行顺序不一样_看完这篇还不懂Redis的RDB持久化,你来打我...

    推荐观看: Redis缓存穿透的终极解决方案,手写布隆过滤器_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili​www.bilibili.com P8架构师串讲:Redis,zookeeper,ka ...

  6. netty发送数据_看完这篇还不清楚Netty的内存管理,那我就哭了

    说明 在学习Netty的时候,ByteBuf随处可见,但是如何高效分配ByteBuf还是很复杂的,Netty的池化内存分配这块还是比较难的,很多人学习过,看过但是还是云里雾里的,本篇文章就是主要来讲解 ...

  7. software reporter tool占用高_看完这篇DBA工作详解,你觉得平均月薪17000真的高吗?...

    DBA(数据库管理员)是企业关键业务应用中非常重要的角色, 数据库管理系统 (DBMS)管理和维护的守护神,位置举足轻重.然而在企业招聘中极少出现相关岗位,更多时候出现在删库跑路的段子里面. 据了解, ...

  8. torch的model加载完怎么看_看完这篇后,别再说你不懂JVM类加载机制了~

    精彩推荐 一百期Java面试题汇总SpringBoot内容聚合IntelliJ IDEA内容聚合Mybatis内容聚合 Class类文件的结构 任何一个Class文件都对应着唯一一个类或接口的定义信息 ...

  9. python基础教程多少页_看完这篇文章,你的Python基础就差不多了(附200页《Python400集》)...

    说干就干.经过将一个多月的素材整理.编写.打磨,在上周末终于完成了. 写完它的时候,我很兴奋,因为它将是第一本系统介绍 Python技巧使用的中文教程. 它不仅适用于一个刚入坑 Python ,还未接 ...

最新文章

  1. java调用项目中的文件_详解eclipse项目中.classpath文件的使用
  2. Server2012R2 ADFS3.0 The same client browser session has made '6' requests in the last '13'seconds
  3. 2015年IT领域里Docker和其它颠覆性的趋势
  4. 实物贴图风格拟物图标素材,高逼格即显
  5. swoole深入学习 2. tcp Server和tcp Client
  6. 动态内存分配(malloc函数)
  7. linux命令行彩蛋,技术|11个无用而有趣的Linux终端彩蛋
  8. Ajax请求破解百度云限速下载教程方法(图片教程)
  9. 常用图像像素格式 NV12、NV2、I420、YV12、YUYV
  10. 英文字母的ASCII码值
  11. java调用斑马证卡打印机制卡机ZXP Series 3C打印彩色工作证
  12. 解决Could not locate executable null\bin\winutils.exe in the Hadoop binaries
  13. SuperMap三维专题之倾斜摄影——WebGL加载倾斜摄影数据篇
  14. Notice: Undefined index: 提示解决方法
  15. win7计算机无法连接投影仪,笔记本win7系统连接投影仪显示没信号如何解决?
  16. 常用网站攻击手段及防御方法
  17. magicmatch java_签名图片一键批量生成 使用Java的Webmagic爬虫实现
  18. GTD时间管理,如何收集?| 每天成就更大成功
  19. 阿里云云效流水线教程
  20. 中国人民大学计算机考研贴吧,中国人民大学计算机系统结构考研经验-人大信息学院考研辅导班...

热门文章

  1. swift开发体验,论objective-c与swift的选择
  2. c语言,递归翻转一个单链表,c实现单链表
  3. APL开发日志--2013-01-17
  4. C++学习——c语言和C++语言中的struct
  5. 牛客21805 字符串编码与解码
  6. PHP中foreach遍历循环的使用(两种用法)
  7. 配置信息的优化,类型转换器
  8. java--自动装箱,拆箱
  9. 库存商品表html源码,JSP+Servlet+数据库的方式完成一个简易的库存商品管理系统...
  10. 装入归档文件时出现了一个错误linux_静态链接与动态链接(Linux)