在实际的 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智能指针相关推荐

  1. C++新特性探究(18.3):C++11 weak_ptr智能指针

    C++11 weak_ptr智能指针 1.weak_ptr指针的创建 2.weak_ptr模板类提供的成员方法 例2: 程序执行结果为: 2 1 10

  2. C++新特性探究(18.2):C++11 unique_ptr智能指针详解

    C++11 unique_ptr智能指针   作为智能指针的一种,unique_ptr 指针自然也具备"在适当时机自动释放堆内存空间"的能力.和shared_ptr指针最大的不同之 ...

  3. Java 8新特性探究(二)深入解析默认方法

    转载自 Java 8新特性探究(二)深入解析默认方法 什么是默认方法,为什么要有默认方法 简单说,就是接口可以有实现方法,而且不需要实现类去实现其方法.只需在方法名前面加个default关键字即可. ...

  4. C++新特性探究(13.6):右值引用再探究

    相关博文: C++新特性探究(十三):右值引用(r-value ref)&&探究 C++新特性探究(十六):move constructor移动构造 C++新特性探究(13.5):右值 ...

  5. C++新特性探究(13.5):右值引用

    相关博文: C++新特性探究(十三):右值引用(r-value ref)&&探究 C++新特性探究(十六):move constructor移动构造 C++新特性探究(13.5):右值 ...

  6. C++新特性探究(十六):move constructor移动构造

    相关博文: C++新特性探究(十三):右值引用(r-value ref)&&探究 C++新特性探究(十六):move constructor移动构造 C++新特性探究(13.5):右值 ...

  7. C++新特性探究(十三):右值引用(r-value ref)探究

    相关博文: C++新特性探究(十三):右值引用(r-value ref)&&探究 C++新特性探究(十六):move constructor移动构造 C++新特性探究(13.5):右值 ...

  8. C++新特性探究(十):Lambda

    一. 匿名函数   简短函数,就地书写,调用.即Lambda存在的意义,常用于取代作回调用的简短函数指针与仿函数.   就地书写,因只有函数体,即无函数名,也称匿名函数. 格式 最小的 Lambda: ...

  9. C++新特性探究(9.1):functor仿函数探究

    相关博文:C++新特性探究(九):functor仿函数 Functor 对象模拟函数   把类对象,像函数名一样使用.   仿函数(functor),就是使一个类的使用看上去像一个函数.其实现就是类中 ...

最新文章

  1. 我国IPv6规模要达到世界第一
  2. 网易云信七鱼被推选为“2016企业创服联盟合作伙伴”
  3. rxjs里subscribeToArray的一个JavaScript模拟实现
  4. 扫地机器人欠压检测电路_扫地机器人智能家居必备!靠传感器感知外界环境?...
  5. Qt 独立运行时伴随CMD命令窗口
  6. win10用不了php_WIN10用不了
  7. Jquery—对$()的总结
  8. 【力扣-动态规划入门】【第 4 天】45. 跳跃游戏 II
  9. java jframe 设置背景图片_Java怎么给JFrame添加背景图片
  10. [车联网安全自学篇] Android安全之Android so文件分析「详细版」
  11. 关于缩比F16模型配平结果异常的解释说明
  12. 目前最赚钱快的微信营销几种玩法和模式
  13. arm开发板与windows下的pjsip建立通话
  14. APISIX-Datadog 插件发布,助力用户提高系统的可观测性
  15. E4 B8 80 E5 9D 97 E4 BA 92 E5 8A A8 28 E5 8C 97 E4 ... python解码
  16. Kibana快速上手
  17. 练习:Python 的字符串处理, 一个朴实无华的四则运算计算器,批量计算小学生四则运算表达式
  18. 硬盘分区失败数据怎么恢复
  19. Linux ubuntu下C/C++开发工具安装和开发环境搭建(c/c++,CLion工具)
  20. html开放式标签(单标签)斜杠书写问题

热门文章

  1. 2019.1.31及以前
  2. LevelDB的源码阅读(三) Get操作
  3. 作品2:资源管理器EX(原味浏览图片)
  4. 【转】Scala: Example use for early definition / early initializer / pre-initialized fields
  5. SQL语句性能分析常用命令
  6. 关于nginx upstream的几种配置方式
  7. python变量域名_想尝试使用python进行域名分析,可是没有接触过python,想请教请教。...
  8. 使用遇到的问题_水性漆在使用过程中遇到的问题以及解决方案
  9. 超融合架构的优缺点_知道 超融合基础架构吗
  10. Python+matplotlib数据可视化鼠标悬停自动标注功能实现