引言

资源管理类是防止资源泄漏的有力武器,但是许多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. (转)MySQL数据库引擎ISAM MyISAM HEAP InnoDB的区别

    转自:http://blog.csdn.net/nightelve/article/details/16895917 MySQL数据库引擎取决于MySQL在安装的时候是如何被编译的.要添加一个新的引擎 ...

  2. 基于MongoDB分布式存储进行MapReduce并行查询

    中介绍了如何基于Mongodb进行关系型数据的分布式存储,有了存储就会牵扯到查询.虽然用普通的方式也可以进行查询,但今天要介绍的是如何使用MONGODB中提供的MapReduce功能进行查询.     ...

  3. android之APN

    APN全称是Access Point Name,中文即接入点,是通过手机上网时必须配置的一个参数,它决定了手机通过哪种接入方式来访问网络. android系统把所有的APN都保存在数据库中,数据库绝对 ...

  4. 《深入Java虚拟机学习笔记》- 第18章 finally子句

    本章主要介绍字节码实现的finally子句.包括相关指令以及这些指令的使用方式.此外,本章还介绍了Java源代码中finally子句所展示的一些令人惊讶的特性,并从字节码角度对这些特征进行了解释. 1 ...

  5. MSP430F5438点亮led

    今天只是想点亮一个led灯,因为没有视频,搞得很多的东西都是自己摸,下午本来讲和咨询店家,TMD说好给一点技术支持,结果一点也不给,我真想草泥马了,其实代码早就写出来了,只是哥哥不知道这款开发板还有接 ...

  6. vs2013 报错AccessViolationException 解决方案

    最近 用vs2013 vs2010开发一个web 项目的时候  报AccessViolationException 异常 ,找不到原因 后边网上看了解决方法,试了一下 解决了,具体什么原因搞不清. 下 ...

  7. Objective-C之消息机制

    话说2014年4月编程语言排行榜中Objective-C的使用比又增加了,看来IOS和MAX OS的开发者是真给力呀. 不过个人感觉用不了多久,IOS和Android的开发者收入就不会有那么大的差异了 ...

  8. 对Map按key和value分别排序

    一.理论准备         Map是键值对的集合接口,它的实现类主要包括:HashMap,TreeMap,Hashtable以及LinkedHashMap等.         TreeMap:基于红 ...

  9. VMware 克隆虚拟机或加载新的已安装虚拟机时System eth0不能使用的解决方法

    近年来的大数据应用特别热,特别是Hadoop和Spark.但大家使用这些分布式文件系统和计算框架都需要一个分布式的集群环境,而大家手头一般没有多余的机器部署master和多个slave节点,就只能在V ...

  10. Win7 NFS 设置详解 | X-Space

    Win7 NFS 设置详解 | X-Space Win7 NFS 设置详解