[Effective C++ --015]在资源管理类中提供对原始资源的访问
引言
资源管理类是防止资源泄漏的有力武器,但是许多APIs直接指涉资源,除非你发誓永不使用这样的APIs,否则只得绕过资源管理对象(resource-managing objects)直接访问原始资源(raw resources)。
例如在条款13中引入了智能指针如auto_ptr或tr1::shared_ptr保存factory函数如createInvestment的调用结果:
std::tr1::shared_ptr<Investement> pInv(createInvestment());
有某个处理函数:
int daysHeld(const Investment* pi);
如果我们这样调用函数:
int days = daysHeld(pInv); //无法通过编译!
因为daysHeld需要的是Investment* 指针,但是你传给它的却是个类型为tr1::shared_ptr<Investment>的对象。
这种时候需要一个函数将RAII class对象(本例为tr1::shared_ptr)转换为其所内含的原始资源(本例为Investment*)达成目标有两个做法:显式转换和隐式转换。
■显示转换
提供一个get成员函数,用来执行显式转换。例如tr1::shared_ptr和auto_ptr都提供一个get成员函数来返回智能指针内部的原始指针(副本):
int days = daysHeld(pInv.get());
■隐式转换
就像(几乎)所有智能指针一样,tr1::shared_ptr和auto_ptr也重载了指针取值(pointer dereferencing)操作符(operator->和operator*),它们允许隐式转换至底部原始指针:
class Investment {
public:
bool isTaxFree() const;
...
};
Investment* createInvestment();
std::tr1::shared_ptr<Investment> pi1(createInvestment());
bool taxable1 = pi1->isTaxFree(); // 使用operator->访问资源
std::auto_ptr<Investment> pi2(createInvestment());
bool taxable2 = (*pi2).isTaxFree(); // 使用operator*访问资源
上面的隐式转换依然无法满足daysHeld()函数的要求,这时候我们必须得取得RAII对象内的原始资源。
使用显示转换方法来满足必须调用get()函数,到处如此这般要求使资源管理类使用起来可能让人产生不悦!
另一个做法是提供一个隐式转换函数:
FontHandle getFont(); // 这是个C API,参数已经简化
void releaseFont(FontHandle fh); // 来自同一组C API
void changeFontSize(FontHandle f, int newSize); // 来自同一组C API class Font {
public:
explicit Font(FontHandle fh) // 获得资源
:f(fh)
{} ~Font() {releaseFont(f);} // 释放资源 FontHandle get() const {return f;} // 显式转换函数
operator FontHandle() const{return f;} // 隐式转换函数 private:
FontHandle f;
}
使用场景
int newFontSize;
Font f1(getFont());
...
changeFontSize(f1.get(),newFontSize); // 显式转换 Font f2(getFont());
changeFontSize(f2,newFontSize); // 隐式转换
但是这个隐式转换会增加错误发生机会。例如客户可能会在需要Font时意外得到一个FontHandle:
Font f1(getFont());
...
FontHandle f2 = f1; // 原意是要拷贝一个Font对象,却反而将f1隐式转换为其底部的FontHandle,
// 却反而将f1隐式转换为其底部的FontHandle,
// 然后才复制它。
以上程序有个FontHandle由Font对象f1管理,但那个FontHandle也可以通过直接使用f2取得。
如果当f1被销毁,字体被释放,而f2因此成为"虚吊的"(dangle)
◆总结
1.APIs往往要求访问原始资源(raw resources),所以每个RAII class应该提供一个"取得其所管理的资源"的办法
2.显示转换比较安全,隐式转换对客户比较方便
[Effective C++ --015]在资源管理类中提供对原始资源的访问的更多相关文章
- Effective C++(15) 在资源管理类中提供对原始资源的访问
问题聚焦: 资源管理类是为了对抗资源泄露. 如果一些函数需要访问原始资源,资源管理类应该怎么做呢? 关于资源管理的概念总是显得那么的高大上,其实只是抽象一点. 下面用 ...
- Effective C++ 条款15、16 在资源管理类中提供对原始资源的访问||成对使用new 与 delete要采取相同形式
1.在资源管理类中提供对原始资源的访问 前几个条款很棒,它们是对抗资源泄露的壁垒,但很多APIs直接指向 资源,这个时候,我们需要直接访问原始资源. 这里,有两种方法解决上述问题,我们 ...
- Effective C++ -----条款15:在资源管理类中提供对原始资源的访问
APIs往往要求访问原始资源(raw resources),所以每一个RAII class应该提供一个“取得其所管理之资源”的办法. 对原始资源的访问可能经由显示转换(.get()成员函数或者指针取值 ...
- 条款15:在资源管理类中提供对原始资源的访问(Provide access to raw resources in resource-managing classes)
NOTE: 1.APIs往往要求访问原始资源(raw resources),所以每一个RAII class应该提供一个“取得其所管理之资源”的办法. 2.对原始资源的访问可能经由显示转换或隐式转换.一 ...
- 读书笔记_Effective_C++_条款十五:在资源类管理类中提供对原始资源的访问
void f(int* a) { cout <<* a << endl; } int main() { shared_ptr<int> p(new int(3)); ...
- 读书笔记 effective c++ Item 15 在资源管理类中提供对原生(raw)资源的访问
1.为什么需要访问资源管理类中的原生资源 资源管理类是很奇妙的.它们是防止资源泄漏的堡垒,没有资源泄漏发生是设计良好的系统的一个基本特征.在一个完美的世界中,你需要依赖这样的类来同资源进行交互,绝不 ...
- Effective C++(14) 在资源管理类中小心copying行为
问题聚焦: 上一条款所告诉我们的智能指针,只适合与在堆中的资源,而并非所有资源都是在堆中的. 这时候,我们可能需要建立自己的资源管理类,那么建立自己的资源管理类时,需要注意什么呢?. ...
- [Effective C++ --014]在资源管理类中小心copying行为
第一节 <背景> 条款13中讲到“资源取得的时机便是初始化时机”并由此引出“以对象管理资源”的概念.通常情况下使用std中的auto_ptr(智能指针)和tr1::shared_ptr(引 ...
- effective条款15,在资源管理类中小心copying行为
class A { private: int *p; void lock(){ cout << p << "is lock" << endl; ...
随机推荐
- 阿里云主机安装Memcached
http://www.zyuns.com/?page_id=354 前言最近发现阿里云主机在使用中,并发访问量稍大,页面加载速度就很慢.于是学习了一些服务器优化的文章,决定安装Memcached,优化 ...
- Fragment中Button的android:onClick 无法监听相应
在Fragment的布局文件中,Button控件下添加android:onClick监听: 1.fragment_main.xml <RelativeLayout xmlns:android=& ...
- POJ 2352 Stars
题意:有一堆星星,每个星星的级别为坐标不高于它且不在它右边的星星个数,求级别为0-n - 1的星星个数. 解法:树状数组.输入的星星坐标已经按y坐标升序排序,y坐标相等的按x升序排序,所以每输入一个数 ...
- java jvm学习笔记八(实现jar包的代码签名)
欢迎装载请说明出处:http://blog.csdn.net/yfqnihao/article/details/8267669 课程源码:http://download.csdn.net/detai ...
- 结构型:代理模式 Vs 适配器模式 Vs 门面模式(外观模式)
先上UML图 代理模式: 适配器模式: 门面模式(外观模式): 打了例子……呃……举个比方 代理模式: 水浒街,西门庆看上潘金莲,想和她嘿咻嘿咻,但是自己有不能去找潘金莲去说,于是他找到了金牌代理人王 ...
- js基础第六天
获取节点属性 getAttribute("属性") 获取属性 setAttribute("属性","值"); 设置节点属性 删除某个属性 r ...
- Windows内核编程之:分页内存与非分页内存 #define PAGEDCODE code_seg("PAGE") (转)
原文链接:http://blog.chinaunix.net/uid-24504987-id-161192.html Windows规定有些虚拟内存可以交换到文件中,这类内存被称为分页内存 有些虚拟内 ...
- Colors
.custom_a1, .custom_a2, .custom_a3, .custom_a4{ width:800px; height:100px; line-height:100px; color: ...
- 计算N的阶层
int factorial(int n) { int i, result; ; i <= n; i++) result *= i; return result; } int factorial2 ...
- NOIP2006 金明的预算方案
1. 金明的预算方案 (budget.pas/c/cpp) [问题描述] 金明今天很开心,家里购置的新房就要领钥匙了,新房里有一间金明自己专用的很宽敞的房间.更让他高兴的是,妈 ...