第一节 <背景>
条款13中讲到“资源取得的时机便是初始化时机”并由此引出“以对象管理资源”的概念。通常情况下使用std中的auto_ptr(智能指针)和tr1::shared_ptr(引数智能指针)作为管理资源的对象。
事实上,这种管理方法十分有效。但是,auto_ptr和tr1::shared_ptr只能管理基于堆(heap-based)的资源,而非heap-based的资源却往往不适合。
因此,有的时候你需要建立自己的资源管理类。本文介绍的内容是在你建立自己的资源管理类时应该注意的事项。

第二节 <正文>
我们知道在C API中处理Mutex的互斥对象,有lock何unlock两个函数可用:

  void lock(Mutex* pm);            // 锁定pm指向的互斥量void unlock(Mutex* pm);          // pm指向的互斥量解锁

假设我们写了Lock类来管理锁。

class  Mutex{
public:Mutex():Count(0){}
public:int Count;
};
void lock(Mutex* pm){pm->Count++;}
void unlock(Mutex* pm){pm->Count--;}
class Lock
{
public:explicit Lock(Mutex* pm):mutexPtr(pm){lock(mutexPtr);}          // 将mutexPtr指向的互斥变量加锁~Lock(){unlock(mutexPtr);} // 将mutexPtr指向的互斥变量解锁
private :Mutex * mutexPtr;
};

上面代码满足RAII(Resource Acquisition is Initialization)原则即,资源在获取时既是初始化时,失去时既是清理时。
想象下面的场景时,程序的输出结果是什么。

1     Mutex m;
2     cout << "Mutex is " << m.Count << endl;
3     Lock m1(&m);
4     cout << "Mutex is " << m.Count << endl;
5     Lock m2(m1);
6     cout << "Mutex is " << m.Count << endl;
7     m1.~Lock();
8     cout << "Mutex is " << m.Count << endl;

输出结果为:

Mutex is 0
Mutex is 1
Mutex is 1
Mutex is 0

这是为什么呢?前两个0和1输出无可厚非,第三个的输出为拿m1作为实例对象去赋值给m2,操作对象为m1,不会直接影响m;第四个互斥量m的管理者m1被销毁了,那么m也就被解锁了。

在上面的例子中,m的值不断被变更,显然,这种资源的管理的方式是不合理的。

可能的解决方法:

1.禁止复制。禁止复制的做法具体的可参照条款6的说明。

class UnCopyable {
public:UnCopyable(){}
private:UnCopyable(const UnCopyable& ths) {}
};
class Lock:private UnCopyable {...
}

2.使用引用计数智能指针:tr1::shared_ptr。

从条款13我们已经知道引用计数智能指针会跟踪使用该资源的所有对象数,计数为0时,资源会被删除。注意,这里删除互斥量m不是我们所期待的,我们期待是解锁互斥量

幸运的是tr1::shared_ptr允许自定义所谓的“删除”动作,该动作是在计数为0时执行的。于是类Lock可以是下面的样子。

class Lock
{
public:explicit Lock(Mutex* pm):mutexPtr(pm,unlock){lock(mutexPtr.get());}          // 将mutexPtr指向的互斥变量加锁
private :shared_ptr<Mutex> mutexPtr;
};

有没有发觉貌似少了点东西?对,析构函数没有了。因为share_ptr会帮你完成这一工作。

3.复制管理对象时也复制所管理的资源。

请回头想一个问题:为什么需要自己的资源管理类?那么,可能的理由是当不需要某个资源时,资源能被正常释放(删除,其他动作)。资源存在多个复件并不可怕,可怕的是复件在该销毁的时候却没有销毁。也就是,管理对象与所管理的资源要一一对应。为了保证这种对应关系,在复制管理对象时也复制所管理的资源。

4.转移资源的管理权。

在某些特殊场合下,你可能希望资源只被一个对象拥有,也就是管理对象在copying时要进行资源所有权的转移。从条款13中讲到的auto_ptr可以完美的实现这个需求。

■总结
1.复制管理对象时,请一并复制对象所管理的资源,资源的copy行为决定了管理对象的copy行为
2.普遍的RAII class的copy行为是抑制复制,使用引用计数

转载于:https://www.cnblogs.com/hustcser/p/4103527.html

[Effective C++ --014]在资源管理类中小心copying行为相关推荐

  1. [Effective C++]条款14:在资源管理类中小心copying行为

    复制 RAII 对象必须一并复制它所管理的资源,所以资源的 copying 行为决定 RAII 对象的 copying 行为 普遍而常见的 RAII class copying 行为是:阻止 copy ...

  2. Effective Java之在公有类中使用访问方法而非公有域(十四)

    1.对于公有类来说,如果类可以在它所在的包的外部进行访问,就提供访问方法,以保留将来改变该类的内部表示法的灵活性. 如果公有域暴露了他的数据域,要想在将来改变它的内部表示法是不可能的,因为公有类的客户 ...

  3. Effective C++ 3nd笔记——资源管理

    Effective C++ 3nd---资源管理 以对象管理资源 简单来说就是要用类来管理资源,最好使用C++11新标准提供的几种智能指针 请记住: 为防止资源泄漏,请使用RAII对象,他们在构造函数 ...

  4. 《Effective C++ 3th》——资源管理

    文章目录 资源如何释放? 注意资源的唯一性 由使用智能指针引出的问题 以对象管理资源 在资源管理类中小心coping行为 在资源管理类中提供对原始资源的访问 成对使用new和delete时要采取相同形 ...

  5. [.NET] 《Effective C#》快速笔记 - C# 中的动态编程

    <Effective C#>快速笔记 - C# 中的动态编程 静态类型和动态类型各有所长,静态类型能够让编译器帮你找出更多的错误,因为编译器能够在编译时进行大部分的检查工作.C# 是一种静 ...

  6. 扩展Visual Studio 2010服务器资源管理器中的SharePoint结点

    Visual Studio 2010最大的卖点就是可扩展性.这样就可以借助.NET社区的力量基于VS构建出许多有用的工具.本文中我们将展示如何扩展VS2010的服务器资源管理器,在其中的SharePo ...

  7. 为什么要在Java的Serializable类中使用SerialVersionUID

    序列化和SerialVersionUID始终是许多Java开发人员的难题. 我经常会看到类似此SerialVersionUID的问题,或者如果不在我的Serializable类中声明SerialVer ...

  8. java枚举类中字段有没有必要加final____枚举类字段 Field ‘xxx‘ may be ‘final‘

    java枚举类中字段有没有必要加final 今天在写一个系统统一返回码的枚举类时候,突然想到一个问题,当不小心手抖给枚举类自动生成了set方法,而恰巧在用的地方不小心用了set方法,从而修改了code ...

  9. C++类中的枚举类型

    在看effective c++的时候,其中第二条边指出.尽量使用const ,enum代替define.在写程序的时候,需要入参为设备类型,第一反应是枚举一个设备类型,并以名字命名.但是有一个问题挺困 ...

最新文章

  1. python对象编程例子-python面向对象编程练习
  2. java订单编号生产代码,java 订单编号 生成器,可用于生产环境
  3. 如何处理SAP Fiori gateway service使用过程中遇到的404 error
  4. Anaconda管理多版本的python环境
  5. angularjs中按回车事件_在AutoCAD中巧用空格键或回车键,制图效率高
  6. IntelliJ IDEA 运行你的第一个Java应用程序
  7. 软件_避免用chrome进行网站配置调试[博]
  8. javascript 基础之事件(event)-------1
  9. 我从不劝退,我就是退。
  10. 5.3 数据通路-专用通路
  11. IE8升级到IE11 F12报错的解决方案
  12. 科技热点周刊|ClickHouse 融资 2.5 亿美元、个人信息保护法正式实施、Facebook 改名 Meta
  13. 3GPP中的各种缩写
  14. 【网络工程】计算机网络专业术语概论全面整理
  15. Ubuntu设置1080分辨率
  16. 惊闻母校徐兵老师英年早逝
  17. 华为云早报 谷歌亚马逊抢食美军100亿美元云计划
  18. 英语学习单词篇(12)
  19. 电驴提示“该内容尚未提供权利证明,无法提供下载”之解决办法详解
  20. php多张图合成一张图,PHP中多张图片合成一张图片例子

热门文章

  1. wps2019去弹窗广告和屏保
  2. Direct2D学习教程(一)
  3. 全球及中国企业级多级单元(MLC)闪存行业研究及十四五规划分析报告
  4. 服务器终端授权,终端服务器许可 - Windows Server | Microsoft Docs
  5. Protel99 SE进行射频电路PCB设计的流程【转】
  6. 服务端发现2t3ik.p进程占CPU过高。2t3ik ddgs.3011
  7. 【USB接口】USB-Type-A B C 、Micro-USB、Mini-USB接口描述
  8. 在Word中隐藏文字
  9. 当咖啡师,开咖啡店,要学哪些东西
  10. 502 bad gateway是什么意思?502 bad gateway怎么解决!