文档章节

使用对象来管理资源

Lennie002
 Lennie002
发布于 2015/10/17 22:32
字数 894
阅读 34
收藏 2

熟悉智能指针的人肯定不会对此觉得陌生。利用C++中对象自动析构的特性,自动地释放资源。 C++编译器并未提供自动的垃圾回收机制,因此释放资源的责任落在了开发者的头上。 我们被要求总是成对地使用newdelete,例如:

Investment *pInv = createInvestment(); ... delete pInv;

createInvestment这样的方法属于工厂方法(factory function),用来创建一个对象的实例。

上述代码确实能够在不泄漏内存的情况下很好地执行,但问题出在createInvestment()函数把释放资源的责任交给了客户, 但并未显式地声明这一点,因而客户有时并不知情。即使客户知道该资源需要销毁, 也可能由于流控制语句或者异常的出现而使得资源未被及时释放。

幸运的是,我们可以用对象来包装资源,并在析构函数中释放它。这样客户便不需要维护资源的内存了。 std::auto_ptr便是这样一个对象,它被称为智能指针(smart pointer)。 典型的使用场景是,资源在堆空间中存储但只在局部被使用。

void f()
{   
     std::auto_ptr<Investment> pInv(createInvestment()); 
}

 

f()调用结束时pInv退出作用域,析构函数被调用,最终使得资源被释放。

 事实上,让createInvestment直接返回智能指针是更好的设计。 

可以看到,使用对象来管理资源的关键在于:创建资源后立即放入资源管理对象中,并利用资源管理对象的析构函数来确保资源被释放

资源管理对象的实现框架正是RAII原则:acquisition is initialization,用一个资源来初始化一个智能指针。指针的析构函数中释放资源。

值得注意的是,为了防止对象被多次释放,auto_ptr应当是不可复制的。

 复制一个auto_ptr会使它变成空,资源被交付给另一个只能指针。

std::auto_ptr<int> p1 (new int);
 *p1.get()=10; 
 std::auto_ptr<int> p2 (p1); 
 std::cout << "p2 points to " << *p2 << '\n'; 
 // p2 points to 10 
 // (p1 is now null-pointer auto_ptr)

.get方法返回资源的指针。

auto_ptr古怪的复制行为导致它并不是管理资源的最佳方式,甚至在STL中auto_ptr的容器也是不允许的: 可以创建这样的容器,但往里面添加元素(例如push_back)时会导致编译错。

auto_ptr<int> p1(new int); vector<auto_ptr<int>> v;    
// OK,可以编译 v.push_back(p1);            
// 编译错!

此处我们引入一个引用计数(reference-counting smart pointer,RCSP)的指针shared_ptr 它在没有任何其他指针引用到该资源时,进行资源的释放。不同于垃圾回收器,shared_ptr未能解决环状引用的问题。

值得注意的是auto_ptrshared_ptr只能管理单个资源,因为它们是使用delete而非delete[]来实现资源释放的。常见的错误便是传递数组进去:

std::tr1::shared_ptr<int> spi(new int[1024]);

在最新的C++标准中,智能指针已经归入std命名空间了。我们可以这样使用:std::shared_ptr<int>

虽然智能指针有这样的问题,但C++并未提供管理数组的智能指针,因为vector等容器就可以很好地完成这个工作。 如果你真的需要,可以求助与Boost社区的boost::scoped_arrayboost::shared_array

 

本文转载自:http://harttle.com/2015/08/02/effective-cpp-13.html

Lennie002
粉丝 8
博文 120
码字总数 64058
作品 0
大连
私信 提问
加载中

评论(0)

windows server 2016 活动目录(二)

AD对象 AD对象类型 用户 在AD域默认可以登陆任何具备信任关系的域中的计算机 访问应用,服务运行账户 访问网络资源(SSO) 默认加入域中的计算机,被域用户登陆后,在访问资源时,默认使用登...

haitao0228
2018/04/20
0
0
SQL Server 2008最直观的变化下(四)

继续来总结SQL Server 2008的直观变化。 6,SQL Server 2008引入了“对象资源管理器详细信息”代替了SQL Server 2005的“摘要”,当在SQL Server Management Studio中的对象资源管理器中选择...

terryli
2011/01/14
0
0
Java EE 7 并发编程—Concurrency Utilities

Executor API的相关介绍可以在由Oracle维护的Java SE文档——High Level Concurrency Objects中找到。Executor API向开发者提供一系列的对象实现高效的线程管理。通常来说,这种高效是由一些...

旋转木马-千里马
2016/01/19
54
0
(三)Kubernetes 快速入门

Kubernetes的核心对象 提供了风格的编程接口,其管理的资源是中的端点,用于存储某种对象的集合,例如,内置资源是包含了所有对象的集合。资源对象是用于表现集群状态的实体,常用于描述应于...

别来无恙-
2019/11/04
0
0
Effective C++ 资源管理小结

我发现,第一遍读书总是不能清楚的认识到问题的本质,我们还需要回过头去总结,因此,我决定以后每读一部分的书,写一点的总结,一方面可以让自己整理知识,另一方面方便以后对比思想。 资源...

长平狐
2012/11/12
84
0

没有更多内容

加载失败,请刷新页面

加载更多

郑州开医疗器械发票

郑州开医疗器械发票【132 * 50 52 * 90 89】罗生,诚、信、合、作,保、真、售、后、保、障、长、期、有、效。adb的全称为Android Debug Bri...

zhangyongli
27分钟前
46
0
OSChina 周四乱弹 —— 失业后的阳光太刺眼了

Osc乱弹歌单(2020)请戳(这里) 【今日歌曲】 @大又 :分享Jack Stauber的单曲《Fighter》 《Fighter》- Jack Stauber 手机党少年们想听歌,请使劲儿戳(这里) @theLovelyBugfly :笑死我...

小小编辑
今天
66
0
手把手教你搭建 ELK 实时日志分析平台

本篇文章主要是手把手教你搭建 ELK 实时日志分析平台,那么,ELK 到底是什么呢? ELK 是三个开源项目的首字母缩写,这三个项目分别是:Elasticsearch、Logstash 和 Kibana。 Elasticsearch ...

武培轩
今天
86
0
直播报名 | Service Mesh技术实践分享

近年来,云原生(Cloud Native)逐渐成为一个技术领域内的流行语,热度居高不下。企业正在加速拥抱云原生架构,以此缩短产品发布周期、敏捷响应市场需求,继而从云计算服务中提炼新的价值和技...

百度开发者中心
今天
97
0
Qt 实现QTableView单元格多按钮效果

实现效果预览: 思路: 使用Qt的委托类独自渲染表格的某一列,如上图字段2的那一列。该一个单元格放入多个按钮,重写 QStyledItemDelegate 委托类 paint 方法即可实现上图效果。 代码: 委托...

剑是SR剑
今天
99
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部