文档章节

使用对象来管理资源

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
博文 118
码字总数 63785
作品 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
Effective C++ 资源管理小结

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

长平狐
2012/11/12
60
0
SQL Server 2008最直观的变化下(四)

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

terryli
2011/01/14
0
0
C++智能指针的分析与使用

手动管理的弊端 在简单的程序中,我们不大可能忘记释放 new 出来的指针,但是随着程序规模的增大,我们忘了 delete 的概率也随之增大。在 C++ 中 new 出来的指针,赋值意味着引用的传递,当赋...

Tanswer_
01/11
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

人生苦短:Python里的17个“超赞操作

人生苦短,我选Python”。那么,你真的掌握了Python吗? 1. 交换变量 有时候,当我们要交换两个变量的值时,一种常规的方法是创建一个临时变量,然后用它来进行交换。比如: # 输入 a = 5 b ...

糖宝lsh
45分钟前
4
0
咕泡-spring中常用设计模式概述

设计模式就是经验之谈,供后人借鉴,解决一些具有代表性的问题 设计模式来源于生活,反过来帮助我们更好生活 设计模式提升代码的可读性、可扩展性、维护成本、复杂业务问题 千万不要死记硬背...

职业搬砖20年
今天
2
0
day59-20180817-流利阅读笔记-待学习

假·照骗,真·社交焦虑 雪梨 2018-08-17 1.今日导读 发朋友圈之前,不少人为了展现更美好的生活状态会对照片加以“微调”,或是加个滤镜显得逼格更高,或是磨个皮瘦个脸拉个大长腿。现在,国...

aibinxiao
今天
23
0
OSChina 周五乱弹 —— 姑娘在这个节日里表白你接受么?

Osc乱弹歌单(2018)请戳(这里) 【今日歌曲】 @Sharon啊:完全被这个小姐姐圈粉了,学两首她的歌去哈哈 分享王贰浪的单曲《往后余生(翻自 马良)》 《往后余生(翻自 马良)》- 王贰浪 手...

小小编辑
今天
1K
16
为什么HashMap要自己实现writeObject和readObject方法?

为什么HashMap要自己实现writeObject和readObject方法? 如果你有仔细阅读过HashMap的源码,那么你一定注意过一个问题:HashMap中有两个私有方法。 private void writeObject(java.io.Objec...

DemonsI
今天
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部