C++新特性探究(18.1):C++11 shared_ptr智能指针
在实际的 C++ 开发中,我们经常会遇到诸如程序运行中突然崩溃、程序运行所用内存越来越多最终不得不重启等问题,这些问题往往都是内存资源管理不当造成的。比如:
有些内存资源已经被释放,但指向它的指针并没有改变指向(成为了野指针),并且后续还在使用;
有些内存资源已经被释放,后期又试图再释放一次(重复释放同一块内存会导致程序运行崩溃);
没有及时释放不再使用的内存资源,造成内存泄漏,程序占用的内存资源越来越多。
针对以上这些情况,很多程序员认为C++语言应该提供更友好的内存管理机制,这样就可以将精力集中于开发项目的各个功能上。
事实上,显示内存管理的替代方案很早就有了,早在1959年前后,就有人提出了“垃圾自动回收”机制。所谓垃圾,指的是那些不再使用或者没有任何指针指向的内存空间,而“回收”则指的是将这些“垃圾”收集起来以便再次利用。
如今,垃圾回收机制已经大行其道,得到了诸多编程语言的支持,例如 Java、Python、C#、PHP等。而C++ 虽然从来没有公开得支持过垃圾回收机制,但C++98/03 标准中,支持使用auto_ptr 智能指针来实现堆内存的自动回收;C++11 新标准在废弃auto_ptr的同时,增添了unique_ptr、shared_ptr以及weak_ptr这3个智能指针来实现堆内存的自动回收。
所谓智能指针,可以从字面上理解为“智能”的指针。具体来讲,智能指针和普通指针的用法是相似的,不同之处在于,智能指针可以在适当时机自动释放分配的内存。也就是说,使用智能指针可以很好地避免“忘记释放内存而导致内存泄漏”问题出现。由此可见,C++也逐渐开始支持垃圾回收机制了,尽管目前支持程度还有限。
C++智能指针底层是采用引用计数的方式实现的。简单的理解,智能指针在申请堆内存空间的同时,会为其配备一个整形值(初始值为 1),每当有新对象使用此堆内存时,该整形值 +1;反之,每当使用此堆内存的对象被释放时,该整形值减 1。当堆空间对应的整形值为0时,即表明不再有对象使用它,该堆空间就会被释放掉。
C++11 shared_ptr智能指针
实际上,每种智能指针都是以类模板的方式实现的,shared_ptr 也不例外。shared_ptr<T>(其中 T 表示指针指向的具体数据类型)的定义位于头文件,并位于 std 命名空间中,因此在使用该类型指针时,程序中应包含如下 2 行代码:
注意,第 2 行代码并不是必须的,也可以不添加,则后续在使用 shared_ptr 智能指针时,就需要明确指明std::
值得一提的是,和 unique_ptr、weak_ptr 不同之处在于,多个 shared_ptr 智能指针可以共同使用同一块堆内存。并且,由于该类型智能指针在实现上采用的是引用计数机制,即便有一个 shared_ptr 指针放弃了堆内存的“使用权”(引用计数减 1),也不会影响其他指向同一堆内存的 shared_ptr 指针(只有引用计数为 0 时,堆内存才会被自动释放)。
1、shared_ptr智能指针的创建
shared_ptr<T>类模板中,提供了多种实用的构造函数,这里给读者列举了几个常用的构造函数(以构建指向 int 类型数据的智能指针为例)。
如上所示,p3 和 p4 都是 shared_ptr 类型的智能指针,因此可以用 p3 来初始化 p4,由于 p3 是左值,因此会调用拷贝构造函数。需要注意的是,如果 p3 为空智能指针,则 p4 也为空智能指针,其引用计数初始值为 0;反之,则表明 p4 和 p3 指向同一块堆内存,同时该堆空间的引用计数会加 1。
而对于 std::move(p4) 来说,该函数会强制将 p4 转换成对应的右值,因此初始化 p5 调用的是移动构造函数。另外和调用拷贝构造函数不同,用 std::move(p4) 初始化 p5,会使得 p5 拥有了 p4 的堆内存,而 p4 则变成了空智能指针。
2、shared_ptr<T>模板类提供的成员方法
例1:
程序执行结果为:
10
p1 为空
10
1
参考博客:详解C++11智能指针
参考博客:C++ 智能指针
C++新特性探究(18.1):C++11 shared_ptr智能指针相关推荐
- C++新特性探究(18.3):C++11 weak_ptr智能指针
C++11 weak_ptr智能指针 1.weak_ptr指针的创建 2.weak_ptr模板类提供的成员方法 例2: 程序执行结果为: 2 1 10
- C++新特性探究(18.2):C++11 unique_ptr智能指针详解
C++11 unique_ptr智能指针 作为智能指针的一种,unique_ptr 指针自然也具备"在适当时机自动释放堆内存空间"的能力.和shared_ptr指针最大的不同之 ...
- Java 8新特性探究(二)深入解析默认方法
转载自 Java 8新特性探究(二)深入解析默认方法 什么是默认方法,为什么要有默认方法 简单说,就是接口可以有实现方法,而且不需要实现类去实现其方法.只需在方法名前面加个default关键字即可. ...
- C++新特性探究(13.6):右值引用再探究
相关博文: C++新特性探究(十三):右值引用(r-value ref)&&探究 C++新特性探究(十六):move constructor移动构造 C++新特性探究(13.5):右值 ...
- C++新特性探究(13.5):右值引用
相关博文: C++新特性探究(十三):右值引用(r-value ref)&&探究 C++新特性探究(十六):move constructor移动构造 C++新特性探究(13.5):右值 ...
- C++新特性探究(十六):move constructor移动构造
相关博文: C++新特性探究(十三):右值引用(r-value ref)&&探究 C++新特性探究(十六):move constructor移动构造 C++新特性探究(13.5):右值 ...
- C++新特性探究(十三):右值引用(r-value ref)探究
相关博文: C++新特性探究(十三):右值引用(r-value ref)&&探究 C++新特性探究(十六):move constructor移动构造 C++新特性探究(13.5):右值 ...
- C++新特性探究(十):Lambda
一. 匿名函数 简短函数,就地书写,调用.即Lambda存在的意义,常用于取代作回调用的简短函数指针与仿函数. 就地书写,因只有函数体,即无函数名,也称匿名函数. 格式 最小的 Lambda: ...
- C++新特性探究(9.1):functor仿函数探究
相关博文:C++新特性探究(九):functor仿函数 Functor 对象模拟函数 把类对象,像函数名一样使用. 仿函数(functor),就是使一个类的使用看上去像一个函数.其实现就是类中 ...
最新文章
- 我国IPv6规模要达到世界第一
- 网易云信七鱼被推选为“2016企业创服联盟合作伙伴”
- rxjs里subscribeToArray的一个JavaScript模拟实现
- 扫地机器人欠压检测电路_扫地机器人智能家居必备!靠传感器感知外界环境?...
- Qt 独立运行时伴随CMD命令窗口
- win10用不了php_WIN10用不了
- Jquery—对$()的总结
- 【力扣-动态规划入门】【第 4 天】45. 跳跃游戏 II
- java jframe 设置背景图片_Java怎么给JFrame添加背景图片
- [车联网安全自学篇] Android安全之Android so文件分析「详细版」
- 关于缩比F16模型配平结果异常的解释说明
- 目前最赚钱快的微信营销几种玩法和模式
- arm开发板与windows下的pjsip建立通话
- APISIX-Datadog 插件发布,助力用户提高系统的可观测性
- E4 B8 80 E5 9D 97 E4 BA 92 E5 8A A8 28 E5 8C 97 E4 ... python解码
- Kibana快速上手
- 练习:Python 的字符串处理, 一个朴实无华的四则运算计算器,批量计算小学生四则运算表达式
- 硬盘分区失败数据怎么恢复
- Linux ubuntu下C/C++开发工具安装和开发环境搭建(c/c++,CLion工具)
- html开放式标签(单标签)斜杠书写问题
热门文章
- 2019.1.31及以前
- LevelDB的源码阅读(三) Get操作
- 作品2:资源管理器EX(原味浏览图片)
- 【转】Scala: Example use for early definition / early initializer / pre-initialized fields
- SQL语句性能分析常用命令
- 关于nginx upstream的几种配置方式
- python变量域名_想尝试使用python进行域名分析,可是没有接触过python,想请教请教。...
- 使用遇到的问题_水性漆在使用过程中遇到的问题以及解决方案
- 超融合架构的优缺点_知道 超融合基础架构吗
- Python+matplotlib数据可视化鼠标悬停自动标注功能实现