条款14:在资源管理类中小心copying行为
请牢记:
1、复制RAII对象必须一并复制它所管理的资源,所以资源的copying行为决定RAII对象的copying行为。
2、普遍常见的RAII class copying行为是:抑制copying、施行引用计数法。不过其他行为也可能被实现。
auto_ptr和tr1::shared_ptr的观念表现在heap_based资源上。然而并非所有资源都是heap_based,对于非heap_based资源而言,需要建立自己的资源管理类。
假设我们使用C API函数出来类型为Mutex的互斥器对象(mutex objects),共有lock和unlock两个函数。
void lock(Mutex* pm); //锁定pm所指的互斥器
void unlock(Mutex* pm); //将互斥器解除锁定
为确保绝不会忘记将一个被锁住的Mutex解锁,创建一个Lock class 来管理机锁。这样的class的基本结构由RAII守则支配,也就是“资源在构造期间获得,在析构期间释放”:
class Lock
{
public:
explicit Lock(Mutex* pm)
: mutexPtr(pm)
{
Lock(mutexPtr); //获得资源
}
~Lock()
{
unlock(mutexPtr); //释放资源
}
private:
Mutex *mutexPtr;
};
客户对Lock的用法符合RAII方式:
Mutex m;
...
{
Lock ml(&m); //锁定互斥器
...
} //在区块末尾,自动解除互斥器锁定
如果此时Lock对象被复制:
Lock ml1(&m); //锁定m
Lock ml2(ml1); //将ml1复制到ml2上,会发生什么?
可能有以下两种选择:
禁止复制:许多时候允许RAII对象复制并不合理:
如果没有按需要定义复制构造函数和赋值操作符,那么得到的结果通常是:非内存资源被创建一次,释放多次。
禁止方式:将copying操作声明为private。
class Lock : private Uncopyable //禁止复制。见条款6
{
public:
... //如前
};
如果需要复制,重新定义复制构造函数和赋值操作符是必须的。
怎么写它们是一个问题,具体的方案依赖于实际的需要,可以使用深拷贝,也可以使用类似于 shared_ptr 的引用计数机制,或者传递所有权。
对底层资源采用引用计数法:
复制RAII对象时,将该资源的“被引用数”递增。例:shared_ptr。
shared_ptr的缺省行为是“当引用次数为0时删除所指物”,但是上面的例子我们想要的动作是解除lock而非删除。
好在shared_ptr允许指定“删除器”:
class Lock
{
public:
explicit Lock(Mutex* pm):mutexPtr(pm,unlock) //以某个mutex初始化shared_ptr,并以unlock函数为删除器
{lock(mutexPtr.get());} //条款15 ~Lock(){unlock(mutexPtr);} //释放资源
private:
std::tr1::shared_ptr<Mutex> mutexPtr;
};
深度拷贝:
某些标准字符串类型是“指向heap内存”之指针构成。这样的字符串对象被复制,不论指针或其所指内存都会被制作出一个复件。这样的字符串展现深度复制行为。
转移底部资源的拥有权:
auto_ptr奉行的复制意义:RAII对象被复制,资源的拥有权从被复制物转移到目标物。
条款14:在资源管理类中小心copying行为的更多相关文章
- Effective C++ -----条款14: 在资源管理类中小心copying行为
复制RAII对象必须一并复制它所管理的资源,所以资源的copying行为决定RAII对象的copying行为. 普遍而常见的RAII class copying行为是:抑制copying(使用私有继承 ...
- Effective C++(14) 在资源管理类中小心copying行为
问题聚焦: 上一条款所告诉我们的智能指针,只适合与在堆中的资源,而并非所有资源都是在堆中的. 这时候,我们可能需要建立自己的资源管理类,那么建立自己的资源管理类时,需要注意什么呢?. ...
- effective条款15,在资源管理类中小心copying行为
class A { private: int *p; void lock(){ cout << p << "is lock" << endl; ...
- 【14】在资源管理类中小心copying行为
1.为什么要使用资源管理类? 资源管理类的思路就是,栈上的对象,封装堆上分配的资源,确保一定会释放资源.auto_ptr和shared_ptr就是资源管理类,行为上像指针. 2.auto_ptr和sh ...
- EC笔记:第三部分:14、在资源管理类中小心Copying行为
场景 上一节实现了智能指针,其中的拷贝构造函数和赋值运算符是通过增加/减少指针的引用计数来操作的.但是如果是管理一个独占资源呢?我们希望在一个资源使用时被锁定,在使用完毕后被释放. #include ...
- [Effective C++ --014]在资源管理类中小心copying行为
第一节 <背景> 条款13中讲到“资源取得的时机便是初始化时机”并由此引出“以对象管理资源”的概念.通常情况下使用std中的auto_ptr(智能指针)和tr1::shared_ptr(引 ...
- Effective C++ 条款13/14 以对象管理资源 || 在资源管理类中小心拷贝行为
三.资源管理 资源就是一旦你使用了它,将来不用的时候必须归还系统.C++中最常用的资源就是动态内存分配.其实,资源还有 文件描述符.互斥器.图形界面中的字形.画刷.数据库连接.socket ...
- Effective C++ 条款15、16 在资源管理类中提供对原始资源的访问||成对使用new 与 delete要采取相同形式
1.在资源管理类中提供对原始资源的访问 前几个条款很棒,它们是对抗资源泄露的壁垒,但很多APIs直接指向 资源,这个时候,我们需要直接访问原始资源. 这里,有两种方法解决上述问题,我们 ...
- 读书笔记 effective c++ Item 15 在资源管理类中提供对原生(raw)资源的访问
1.为什么需要访问资源管理类中的原生资源 资源管理类是很奇妙的.它们是防止资源泄漏的堡垒,没有资源泄漏发生是设计良好的系统的一个基本特征.在一个完美的世界中,你需要依赖这样的类来同资源进行交互,绝不 ...
随机推荐
- 6LoWPAN - Transmission of IPv6 Packets over IEEE 802.15.4 Networks
6LoWPAN covered topics include the following: Frame format for transmission of IPv6 packets Method ...
- 链接hdf5库出现错误的解决办法
作者:朱金灿 来源:http://blog.csdn.net/clever101 在链接hdf5库出现一些链接错误: error LNK2001: 无法解析的外部符号 _H5T_NATIVE_DOUB ...
- win7 64位系统下进入debug
win7 64位无法直接通过命名行输入debug命令的方式进入到debug,好在我们可是使用一个工具DOSbox来进入debug.操作步骤如下:1.下载DOSbox进行安装.下载地址:点击打开链接.如 ...
- Redis 宝典 | 基础、高级特性与性能调优
转载:Redis 宝典 | 基础.高级特性与性能调优 本文由 DevOpsDays 本文由简书作者kelgon供稿,高效运维社区致力于陪伴您的职业生涯,与您一起愉快的成长. 作者:kelgon ...
- c语言学习笔记(8)——函数
学完c语言的函数可以理解面向过程的语言 函数是c语言的重点 一.为什么需要函数? 1.避免了重复性操作 2.有利于程序的模块化(每一个功能可以用不同函数去实现) 二.什么叫做函数? 逻辑上:能够完成特 ...
- matlab 工具函数 —— logdet(A)
当参数 A 是正定矩阵(positive definite)时,logdet 利用相关矩阵分解的性质,将比 log(det(A)) 获得更快的效率: function y = logdet(A) tr ...
- WPF 3D中多个模型如何设置某一个在最前?
原文:WPF 3D中多个模型如何设置某一个在最前? 问题:我们的模型包括导入的3D solid模型和axis坐标轴模型,当模型旋转的时候,3D会将axis挡住. 期望:axis一直在最前面,不会被3D ...
- 代码首要的目标应该是“解决问题”(包括“没有 bug”),其次的目标才是“简单优雅”。
什么是现实理想主义者 曾经有人看了我的文章,以为我是一个“理想主义者”,来找我聊天.他说:“你知道吗,我跟你一样喜欢简单优雅的代码.上次我在某公司工作,看到他们的代码乱得不成样子,二话没说给他们重写了 ...
- 网络编程Socket它TCP它TIME_WAIT国家具体解释
下面我们用最简单的一对一的客户server编程模型重现遇到的一些问题: 初学者socket当写作socket名其妙的问题.比方说bind函数返回的常见错误是EADDRINUSE 使用以下的程序重现这个 ...
- 【Java】Java中的数据类型
Java 语言是一种强类型语言.通俗点说就是,在 Java 中存储的数据都是有类型的,而且必须在编译时就确定其类型.Java 数据类型分为两类,如图: 在 Java 的领域里,基本数据类型变量存的是数 ...