文档章节

使用对象来管理资源

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
博文 121
码字总数 64909
作品 0
大连
私信 提问
利用IDisposable接口构建包含非托管资源对象

托管资源与非托管资源 在.net中,对象使用的资源分为两种:托管资源与非托管资源。托管资源由CLR进行管理,不需要开发人员去人工进行控制,.NET中托管资源主要指“对象在堆中的内存”;非托管...

帆帆帆
11/12
0
0
Java EE 7 并发编程—Concurrency Utilities

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

旋转木马-千里马
2016/01/19
29
0
windows server 2016 活动目录(二)

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

haitao0228
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
Effective C++ 资源管理小结

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

长平狐
2012/11/12
67
0

没有更多内容

加载失败,请刷新页面

加载更多

jquery通过id显示隐藏

var $div3 = $('#div3'); 显示 $div3.show(); 隐藏 $div3.hide();

yan_liu
今天
3
0
《乱世佳人》读书笔记及相关感悟3900字

《乱世佳人》读书笔记及相关感悟3900字: 之前一直听「荔枝」,后来不知怎的转向了「喜马拉雅」,一听就是三年。上班的时候听房产,买房了以后听装修,兴之所至时听旅行,分手后听亲密关系,...

原创小博客
今天
3
0
大数据教程(9.6)map端join实现

上一篇文章讲了mapreduce配合实现join,本节博主将讲述在map端的join实现; 一、需求 实现两个“表”的join操作,其中一个表数据量小,一个表很大,这种场景在实际中非常常见,比如“订单日志...

em_aaron
今天
3
0
cookie与session详解

session与cookie是什么? session与cookie属于一种会话控制技术.常用在身份识别,登录验证,数据传输等.举个例子,就像我们去超市买东西结账的时候,我们要拿出我们的会员卡才会获取优惠.这时...

士兵7
今天
3
0
十万个为什么之为什么大家都说dubbo

Dubbo是什么? 使用背景 dubbo为什么这么流行, 为什么大家都这么喜欢用dubbo; 通过了解分布式开发了解到, 为适应访问量暴增,业务拆分后, 子应用部署在多台服务器上,而多台服务器通过可以通过d...

尾生
今天
5
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部