boost any 实现万能容器_全面剖析 C++ Boost 智能指针!| CSDN 博文精选
![](/assets/blank.gif)
![](/assets/blank.gif)
作者 | .NY&XX
责编 | 屠敏
出品 | CSDN 博客
为什么要使用智能指针
C++没有提供类似JAVA的垃圾回收机制,因此Boost可以通过智能指针来管理内存避免一些问题。C++继承C高效灵活地指针,但是同样带了了很多问题:
内存泄露
野指针
越界访问
什么是智能指针
智能指针是一种像指针的C++对象,但它能够在对象不使用的时候自己销毁掉。虽然STL提供了auto_ptr,但是由于不能同容器一起使用(不支持拷贝和赋值操作),因此很少有人使用。它是Boost各组件中,应用最为广泛的一个。使用智能指针需包含以下头文件,如果只使用智能指针 shared_ptr 可以只包含同名头文件。
#include using namespace boost;
Boost主要包含以下几种智能指针:
boost::scope_ptr
主要特点
scoped_ptr 是Boost 提供的一个简单的智能指针只限于作用域内使用
指针管理权不可转移,不支持拷贝构造函数与赋值操作。
这种智能指针只限于作用域内使用,无法转移内置指针的管理权(不支持拷贝、=赋值等) 但是作用也很显然。例如:
假设定义到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 ,多了下标访问操作,其他类似。
构造函数指针必须是 new 的结果,而不能是 new 表达式的结果
没有 *, -> 操作符重载,因为 scoped_array 持有的不是一个普通指针
析构函数使用 delete 释放资源,而不是 delete
提供 operator 操作符重载,可以像普通数组一样用下标访问
没有 begin, end 等类似容器迭代器操作函数
具体用法
scoped_array 轻巧方便,没有给程序增加额外负担,但是 scoped_array 功能有限,不能动态增长,也没有迭代器支持,不能搭配 STL 算法,仅有一个纯粹的“裸”数组接口。在需要动态数组的情况下我们应该使用 std::vector 。例如:
boost::shared_ptr
主要特点
boost.smart_ptr 库中最有价值,最重要的组成部分。支持拷贝构造函数、支持赋值操作。重载了*和->操作符用来模仿原始指针的行为。目前已成为tr1标准的一部分,发展自原始的auto_ptr,内置引用计数。引用指针计数器记录有多少个引用指针指向同一个对象,如果最后一个引用指针被销毁的时候,那么就销毁对象本身。
支持拷贝构造函数,赋值操作。
重载 * 和 -> 操作符模仿原始指针。
内置引用计数。
但是,使用的时候需要注意以下几点:
同scope_ptr一样,禁止get得到指针地址后,执行delete。
禁止循环引用,否则会出内存泄漏。
不能作为函数的临时参数。
shared_ptr是线程安全的。
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】
boost any 实现万能容器_全面剖析 C++ Boost 智能指针!| CSDN 博文精选相关推荐
- 全面剖析 C++ Boost 智能指针! | CSDN 博文精选
作者 | .NY&XX 责编 | 屠敏 出品 | CSDN 博客 为什么要使用智能指针 C++没有提供类似JAVA的垃圾回收机制,因此Boost可以通过智能指针来管理内存避免一些问题.C++继 ...
- boost::any 万能容器_万能的小苏打,太棒了
阅读本文前,请您先点击上面的蓝色字体,再点击"关注",这样您就可以继续免费收到内容了.每天都有分享.完全是免费订阅,请放心关注. 小苏打(Baking Soda)是商业上的名称,小 ...
- Spring 框架之 AOP 原理深度剖析!|CSDN 博文精选
作者 | GitChat 责编 | 郭芮 出品 | CSDN 博客 AOP(Aspect Oriented Programming)面向切面编程是 Spring 框架最核心的组件之一,它通过对程序结构 ...
- 剖析Focal Loss损失函数: 消除类别不平衡+挖掘难分样本 | CSDN博文精选
作者 | 图像所浩南哥 来源 | CSDN博客 论文名称:< Focal Loss for Dense Object Detection > 论文下载:https://arxiv.org/ ...
- 【举栗子】Docker 容器磁盘占满的几种情况 | CSDN博文精选
戳蓝字"CSDN云计算"关注我们哦! 作者 | isea533 转自 | CSDN博客 责编 | 阿秃 参考文档: https://docs.docker.com/engine/ ...
- 从 Android 6.0 源码的角度剖析 Binder 工作原理 | CSDN 博文精选
在从Android 6.0源码的角度剖析Activity的启动过程一文(https://blog.csdn.net/AndrExpert/article/details/81488503)中,我们了解 ...
- java队列_如何彻底搞懂 Java 数据结构?CSDN 博文精选
作者 | 张振华.Jack 责编 | 郭芮 出品 | CSDN 博客 本文和大家一起来重温<Java数据结构>经典之作. Java数据结构 要理解Java数据结构,必须能清楚何为数据结构? ...
- html 如何实现一条竖线边上有 刻度_记一次腾讯面试:进程之间究竟有哪些通信方式?如何通信? ---- 告别死记硬背||CSDN博文精选...
作者:帅地 有一次面试的时候,被问到进程之间有哪些通信方式,不过由于之前没深入思考且整理过,说的并不好.想必大家也都知道进程有哪些通信方式,可是我猜很多人都是靠着"背"来记忆的,所 ...
- 智能指针的释放_手把手教你实现智能指针
一. 为什么使用智能指针 C++的内存管理是让很多人头疼的事,因为C++语言中没有垃圾回收机制,当我们通过new语句动态申请堆空间时,用完这个堆空间时就得用delete语句释放申请的堆空间,不然就会导 ...
最新文章
- Java系列: JAVA字符串格式化-String.format()的使用(zz)
- 天才大猩猩可可去世,享年 46 岁
- SAP CRM WebClient UI的配置存储数据库表
- arduinopn532模块_树莓派使用libnfc驱动ITEAD NFC PN532模块
- typeorm 生成实体类_android常用orm框架greenDAO创建表生成实体类
- (枚举)餐厅点餐(fzu2086)
- MATLAB矩阵元素的处理
- Golang研学:defer!如何掌握并用好(延迟执行)
- python控制电机正反转_连接电动机正反转控制电路,要求具备电气互锁功能,拍照上传...
- 超级简单基于spring boot高速公路收费系统的设计与实现.rar(含源码及数据库文件)
- 全网多种方法解决未连接到互联网 代理服务器出现问题,或者地址有误的错误
- Weather API 天气应用 API调用分享
- 个人跨境电商要多少钱?新手怎么做跨境电商?
- XC3071充电IC(耐高压,带OVP)
- 【深度域自适应】二、利用DANN实现MNIST和MNIST-M数据集迁移训练
- 发送writely和orkut邀请
- Nacos(二)Linux部署Nacos集群环境(兼容Nacos1.x与2.x)
- x264命令行参数解释
- 微信小程序教程03:WXML语法
- 盛志凡:TVOS技术解读
热门文章
- Eureka Server 集群
- python 百度网盘下载提速_教你如何百度网盘的提高下载速度?
- selenium设置js加载的时限,防止持续加载页面
- numeric转换varchar_将数据类型varchar转换为numeric时选择失败
- mysql双主故障自动切换_MySQL主库高可用 -- 双主单活故障自动切换方案
- python计算夏令时的具体日期,python time.time()和“夏令时”;
- linux常用命令速记
- C# Serializable学习
- 监控管理平台 OpenNMS
- SQL2005 安装时 “性能监视器计数器要求(错误)” 解决方案