引言

资源管理类是防止资源泄漏的有力武器,但是许多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]在资源管理类中提供对原始资源的访问的更多相关文章

  1. Effective C++(15) 在资源管理类中提供对原始资源的访问

      问题聚焦:     资源管理类是为了对抗资源泄露.     如果一些函数需要访问原始资源,资源管理类应该怎么做呢?        关于资源管理的概念总是显得那么的高大上,其实只是抽象一点. 下面用 ...

  2. Effective C++ 条款15、16 在资源管理类中提供对原始资源的访问||成对使用new 与 delete要采取相同形式

    1.在资源管理类中提供对原始资源的访问     前几个条款很棒,它们是对抗资源泄露的壁垒,但很多APIs直接指向 资源,这个时候,我们需要直接访问原始资源.     这里,有两种方法解决上述问题,我们 ...

  3. Effective C++ -----条款15:在资源管理类中提供对原始资源的访问

    APIs往往要求访问原始资源(raw resources),所以每一个RAII class应该提供一个“取得其所管理之资源”的办法. 对原始资源的访问可能经由显示转换(.get()成员函数或者指针取值 ...

  4. 条款15:在资源管理类中提供对原始资源的访问(Provide access to raw resources in resource-managing classes)

    NOTE: 1.APIs往往要求访问原始资源(raw resources),所以每一个RAII class应该提供一个“取得其所管理之资源”的办法. 2.对原始资源的访问可能经由显示转换或隐式转换.一 ...

  5. 读书笔记_Effective_C++_条款十五:在资源类管理类中提供对原始资源的访问

    void f(int* a) { cout <<* a << endl; } int main() { shared_ptr<int> p(new int(3)); ...

  6. 读书笔记 effective c++ Item 15 在资源管理类中提供对原生(raw)资源的访问

    1.为什么需要访问资源管理类中的原生资源  资源管理类是很奇妙的.它们是防止资源泄漏的堡垒,没有资源泄漏发生是设计良好的系统的一个基本特征.在一个完美的世界中,你需要依赖这样的类来同资源进行交互,绝不 ...

  7. Effective C++(14) 在资源管理类中小心copying行为

    问题聚焦:     上一条款所告诉我们的智能指针,只适合与在堆中的资源,而并非所有资源都是在堆中的.     这时候,我们可能需要建立自己的资源管理类,那么建立自己的资源管理类时,需要注意什么呢?. ...

  8. [Effective C++ --014]在资源管理类中小心copying行为

    第一节 <背景> 条款13中讲到“资源取得的时机便是初始化时机”并由此引出“以对象管理资源”的概念.通常情况下使用std中的auto_ptr(智能指针)和tr1::shared_ptr(引 ...

  9. effective条款15,在资源管理类中小心copying行为

    class A { private: int *p; void lock(){ cout << p << "is lock" << endl; ...

随机推荐

  1. [HDU 4828] Grids

    Grids Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others)Total Subm ...

  2. DB2创建序列

    一.创建序列 序列是按照一定的规则生产的数值,序列的作用非常的大,比如银行交易中的流水号,就是记录每笔交易的关键字段. 通过create sequence语句创建序列,具体语法如下: >> ...

  3. (八)学习MVC之三级联动

    1.新建项目,MVC选择基本模板 2.新建类:Model/Student.cs,数据库信息有三个实体:分别是年级.班级和学生. using System; using System.Collectio ...

  4. (二)学习MVC之实现用户注册功能

    学习地址:http://www.cnblogs.com/mzwhj/archive/2012/10/22/2720089.html 本文和学习地址不一样的地方是我自己添加了一些简单的注释和理解. 1. ...

  5. JPA---一对一关系

    在JPA中,使用@oneToOne来标示. package com.yl.demo1.bean.oneToone; import javax.persistence.CascadeType; impo ...

  6. CF GYM 100703A Tea-drinking

    题意:龙要制作n个茶,每个茶的配方是一个字符串,两个字符串之间有一个差值,这个差值为两个字符串每个对应字母之间差的绝对值的最大值,求制作所有茶时获得的所有差值中的最大值. 解法:克鲁斯卡尔.将茶的配方 ...

  7. cdn是什么和作用有些

    内容分发网络其基本思路是尽可能避开互联网上有可能影响数据传输速度和稳定性的瓶颈和环节,使内容传输的更快.更稳定.通过在网络各处放置节点服务器所构 成的在现有的互联网基础之上的一层智能虚拟网络,CDN系 ...

  8. 微信浏览器内置JavaScript 对象:WeixinJSBridge

    微信公众平台开发 微信公众平台开发模式 企业微信公众平台 微信浏览器 分享到朋友圈 发送给好友 分享到腾讯微博 作者:方倍工作室 原文: http://www.cnblogs.com/txw1958/ ...

  9. 【po3693】Maximum repetition substring

    题意: 给定一个字符串 求重复次数最多的连续重复子串 并输出字典序最小方案 题解: 枚举子串长度L 显然如果重复次数>1 那么答案串肯定包含s[1],s[1+L],s[1+L*2],...中的两 ...

  10. iso定制封装

    http://xiaoli110.blog.51cto.com/1724/1617541