作者 | .NY&XX

责编 | 屠敏

出品 | CSDN 博客

为什么要使用智能指针

C++没有提供类似JAVA的垃圾回收机制,因此Boost可以通过智能指针来管理内存避免一些问题。C++继承C高效灵活地指针,但是同样带了了很多问题:

  1. 内存泄露

  2. 野指针

  3. 越界访问

什么是智能指针

智能指针是一种像指针的C++对象,但它能够在对象不使用的时候自己销毁掉。虽然STL提供了auto_ptr,但是由于不能同容器一起使用(不支持拷贝和赋值操作),因此很少有人使用。它是Boost各组件中,应用最为广泛的一个。使用智能指针需包含以下头文件,如果只使用智能指针 shared_ptr 可以只包含同名头文件。

#include <boost/smart_ptr.hpp>using namespace boost;

Boost主要包含以下几种智能指针:

boost::scope_ptr

主要特点

  1. scoped_ptr 是Boost 提供的一个简单的智能指针只限于作用域内使用

  2. 指针管理权不可转移,不支持拷贝构造函数与赋值操作。

这种智能指针只限于作用域内使用,无法转移内置指针的管理权(不支持拷贝、=赋值等) 但是作用也很显然。例如:

假设定义到delete之中…发生了异常,那么ptr就无法被delete,造成了内存泄漏。使用scoped_ptr就可以很好解决这个问题,只需要new的时候放到scoped_ptr之中就可以了。

具体用法

假设:

scoped_ptr ptr_t(new T); // 假设内置指针为p_t

则:

  • ptr_t->get(),返回内部管理的指针,但禁止在get()出来的指针上执行delete。

  • ptr_t->xxx(),等同于p_t->xxx() ptr_t.reset(),delete内部持有的p_t。

  • 假设T支持直接赋值,*ptr_t = xxx。

再次强调,scoped_ptr不能做拷贝、赋值等转移指针管理权限的事情。因此,class内置域为scoped_ptr是不允许的,除非class也禁止拷贝、赋值。

boost::scope_array

主要特点

同 boost::scoped_ptr 基本一样,只是接受数组的new [],多了下标访问操作,其他类似。

  1. 构造函数指针必须是 new[] 的结果,而不能是 new 表达式的结果

  2. 没有 *, -> 操作符重载,因为 scoped_array 持有的不是一个普通指针

  3. 析构函数使用 delete[] 释放资源,而不是 delete

  4. 提供 operator[] 操作符重载,可以像普通数组一样用下标访问

  5. 没有 begin(), end() 等类似容器迭代器操作函数

具体用法

scoped_array 轻巧方便,没有给程序增加额外负担,但是 scoped_array 功能有限,不能动态增长,也没有迭代器支持,不能搭配 STL 算法,仅有一个纯粹的“裸”数组接口。在需要动态数组的情况下我们应该使用 std::vector 。例如:

boost::shared_ptr

主要特点

boost.smart_ptr 库中最有价值,最重要的组成部分。支持拷贝构造函数、支持赋值操作。重载了*和->操作符用来模仿原始指针的行为。目前已成为tr1标准的一部分,发展自原始的auto_ptr,内置引用计数。引用指针计数器记录有多少个引用指针指向同一个对象,如果最后一个引用指针被销毁的时候,那么就销毁对象本身。

  1. 支持拷贝构造函数,赋值操作。

  2. 重载 * 和 -> 操作符模仿原始指针。

  3. 内置引用计数。

但是,使用的时候需要注意以下几点:

  1. 同scope_ptr一样,禁止get()得到指针地址后,执行delete。

  2. 禁止循环引用,否则会出内存泄漏。

  3. 不能作为函数的临时参数。

  4. shared_ptr是线程安全的。

  5. shared_ptr支持强制类型转换,如果定义了一个U能够强制转换到T(因为T是U的基类),那么shared_ptr也能够强制转换到shared_ptr。

具体用法

具体使用例子如下:

当遇到深拷贝问题时,如果成员变量是shared_ptr类型可以考虑不用自己编写拷贝和赋值构造函数。例如:

实际上,智能指针赋值拷贝的同时,引用计数也加1了。在默认析构函数也是如此,析构函数执行之后,会调用类A的析构函数,检查引用计数都为0后,会delete掉这个int。从而完美的完成了无内存泄漏的、无内存出错的、多个实例之间的指针变量共享。

boost::weak_ptr

主要特点

weak_ptr 被设计为与 shared_ptr 共同工作,可以从一个 shared_ptr 或者另一个 weak_ptr 对象构造,获得资源的观测权。但是 weak_ptr 没有共享资源,它的构造不会引起指针引用计数的增加,同时,在析构的时候也不回引起引用计数的减少。

具体用法

shared_ptr有个致命缺陷,循环引用不能够自动回收。看如下的例子:

运行结果:

由于A和B相互引用,它们的计数永远都为2,所以这样使用shared_ptr必然会导致内存泄漏。为了解决这个问题,可以采用boost::weak_ptr来隔断交叉引用中的回路;boost::weak_ptr必须从一个boost::share_ptr或另一个boost::weak_ptr转换而来,这也说明,进行该对象的内存管理的是那个强引用的boost::share_ptr。boost::weak_ptr只是提供了对管理对象的一个访问手段。弱引用不更改引用计数,类似普通指针,只要把循环引用的一方使用弱引用,即可解除循环引用。例如:

运行结果:

shared_ptr 同 weak_ptr的比较:

intrusive_ptr

主要特点

虽然boost::shared_ptr 比普通指针提供了更完善的功能。有一个小小的代价,那就是一个共享指针比普通指针占用更多的空间,每一个对象都有一个共享指针,这个指针有引用计数器以便于释放。boost::intrusive_ptr是一种“侵入式”的引用计数指针,是boost::shared_ptr的插入式版本。实际并不提供引用计数功能,而是要求被存储的对象自己实现引用计数功能。可以应用于以下两种情形:

  • 对内存占用要求非常严格,智能指针大小必须与裸指针一样;

  • 现存代码已经有了引用计数机制管理的对象。而又没有时间去维护它(或者已经不能获取这些代码了)。

intrusive_ptr与使用shared_ptr相比,有两个主要的不同之处。第一个是你需要提供引用计数的机制。第二个是把this当成智能指针是合法的。

具体用法

  • 要使用 boost::intrusive_ptr, 要包含 “boost/intrusive_ptr.hpp” 并定义两个普通函数 intrusive_ptr_add_ref 和 intrusive_ptr_release. 它们都要接受一个参数。

  • 一般最好泛化这两个函数,简单地调用被管理类型的成员函数去完成工作。

我们来看一个例子,RefCount提供了计数器功能:

在主函数中测试一下:

运行结果:

声明:本文为CSDN博主「.NY&XX」的原创文章,版权归作者所有,如需转载请联系作者。

原文:https://blog.csdn.net/songguangfan/article/details/96361648

【END】

2019年Python全栈工程师,都是开发人员改怎么转向高收入?

https://edu.csdn.net/topic/python115?utm_source=csdn_bw

 热 文 推 荐 

☞一套代码两端运行不靠谱?是时候放弃  C++ 跨 Android、iOS 端开发!

高薪的 10 倍工程师不能带来 10 倍的产出?

十步教你如何接手别人的代码!

☞柬埔寨月薪 4 万敲代码?真相是我差点丢了性命!

☞免费公开课 | 基于定制数据流技术的AI计算加速

☞写爬虫,怎么可以不会正则呢?

☞10个业界最流行的Kubernetes发行版

30天200万收入, 我是怎么做区块链游戏的

行!这下 CSDN 玩大了!粉丝:太良心

点击阅读原文,查阅博客原文与作者交流。

你点的每个“在看”,我都认真当成了喜欢

全面剖析 C++ Boost 智能指针! | CSDN 博文精选相关推荐

  1. boost any 实现万能容器_全面剖析 C++ Boost 智能指针!| CSDN 博文精选

    作者 | .NY&XX 责编 | 屠敏 出品 | CSDN 博客 为什么要使用智能指针 C++没有提供类似JAVA的垃圾回收机制,因此Boost可以通过智能指针来管理内存避免一些问题.C++继 ...

  2. 在你的代码中使用Boost智能指针

    在你的代码中使用Boost智能指针 Smart Pointers to boost your code(By peterchen)  翻译 masterlee Download source file ...

  3. 干货:NIST评测(SRE19)获胜团队声纹识别技术分析 | CSDN博文精选

    作者 | xjdier 来源 | CSDN博文精选 (*点击阅读原文,查看作者更多精彩文章) 近日,NIST说话人识别技术评测 (Speaker Recognition Evaluation,SRE) ...

  4. 万字长文详解如何用Python玩转OpenGL | CSDN 博文精选

    作者 | 天元浪子 来源 | CSDN博文精选 [编者按]OpenGL(开放式图形库),用于渲染 2D.3D 矢量图形的跨语言.跨平台的应用程序编程接口,C.C++.Python.Java等语言都能支 ...

  5. 一文读懂GoogLeNet神经网络 | CSDN博文精选

    作者 | .NY&XX 来源 | CSDN博客 本文介绍的是著名的网络结构GoogLeNet,目的是试图领会其中结构设计思想. GoogLeNet特点 优化网络质量的生物学原理 GoogLeN ...

  6. IntelliJ IDEA 2019.3 正式发布,给我们带来哪些新特性?| CSDN 博文精选

    作者 | _YourBatman 责编 | 屠敏 出品 | CSDN 博客 前言 千呼万唤始出来.自从JetBrains在今年7月24日发布了IDEA 2019.2版本后,从9月份开始我便一直在关注此 ...

  7. 利用MTCNN和FaceNet实现人脸检测和人脸识别 | CSDN博文精选

    作者 | pan_jinquan 来源 | CSDN博文精选 (*点击阅读原文,查看作者更多文章) 人脸检测和人脸识别技术算是目前人工智能方面应用最成熟的技术了.本博客将利用MTCNN和FaceNet ...

  8. PyTorch实现L2和L1正则化的方法 | CSDN博文精选

    作者 | pan_jinquan 来源 | CSDN博文精选 目录 1.torch.optim优化器实现L2正则化 2.如何判断正则化作用了模型? 2.1未加入正则化loss和Accuracy 2.1 ...

  9. 使用自己的数据集训练MobileNet、ResNet实现图像分类(TensorFlow)| CSDN博文精选

    作者 | pan_jinquan 来源 | CSDN博文精选 之前写了一篇博客<使用自己的数据集训练GoogLenet InceptionNet V1 V2 V3模型(TensorFlow)&g ...

最新文章

  1. SpringBoot整合Grpc实现跨语言RPC通讯
  2. java 全半角转换_Java 全半角转换
  3. 推荐系统遇上深度学习(一)--FM模型理论和实践
  4. Fedora最小化安装后没有ifconfig命令
  5. SQL 存储过程中,将串连的字符串当表用。
  6. 部署Smokeping
  7. 如何用四个简单的步骤加速 LibreOffice
  8. mongodb adminmongo 使用过程中的一些小问题记录
  9. .net流行面试试题(基础但重要)
  10. 导出DataTable数据到Word或者Excel
  11. csdn笔记怎么用看这里
  12. java菜鸟驿站_RxJava菜鸟驿站(一)
  13. 社交网络影响力最大化——贪心算法实现(Python实现)
  14. 元宇宙持续引发关注,微软计划明年发布相关产品 | 产业区块链发展周报
  15. pwa 让你的网页可以像本地程序一样安装到电脑上,Youtube网站使用的也是当前方法 (chrome版本)
  16. 简单的rpg任务制作
  17. 产品造型设计上的加减法的运用
  18. PHP使用socket TCP通信对接富途牛牛
  19. 赠与今年的大学毕业生
  20. 【论文阅读】查询搜索中的安全和效率权衡(ACM 10.1145)

热门文章

  1. Hive中外部表的alter与drop操作的最低权限要求
  2. 2015 - Deep recurrent q-learning for partially observable MDPs
  3. java ftl crud_使用JDBC完成CRUD(增删改查)
  4. mysql数据类型及语法_mysql8 参考手册--Numeric数据类型语法
  5. 传递json_开发技巧分享—JSON 数据格式及函数讲解
  6. windows无法访问指定设备_恢复 你的电脑/设备需要修改 未连接或无法访问所需设备。...
  7. 内联滴灌行业调研报告 - 市场现状分析与发展前景预测
  8. 以太网接入设备行业调研报告 - 市场现状分析与发展前景预测(2021-2027年)
  9. 2021年中国云无线接入网(C-RAN)市场趋势报告、技术动态创新及2027年市场预测
  10. 第1章 C/C++与开发环境介绍(《C和C++游戏趣味编程》配套教学视频)