Effective C++ 条款13/14 以对象管理资源 || 在资源管理类中小心拷贝行为
三、资源管理
资源就是一旦你使用了它,将来不用的时候必须归还系统。C++中最常用的资源就是动态内存分配。其实,资源还有 文件描述符、互斥器、图形界面中的字形、画刷、数据库连接、socket等。
1、 以对象管理资源
void f()
{
investment *plv = createInvestment();
//这里存在很多不定因素,可能造成下面语句无法执行,这就存在资源泄露的可能。
delete plv;
}
这里我们把资源放进一个对象里面,然后依赖C++本身的对象里面的析构函数帮我们确保资源被释放。这里用到auto_ptr来解决。这是一个类指针对象,也就是所谓的智能指针。其析构函数自动调用delete。
std::auto_ptr<Investment> pInv1(createInvestment()); //pInv1指向createInvestment()返回物;
std::auto_ptr<Investment> pInv2(pInv1); //现在pInv2指向对象,而pInv1被设为NULL;
pInv1 = pInv2; //现在pInv1指向对象,而pIn2被设为NULL;
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
还有一个问题就是,不能让多个auto_ptr同时指向某一个对象。auto_ptr还有一个特性就是,通过复制之后,其raw 对象被置为null。
所以,我们引用一个 引用计数型智能指针 shared_ptr 。它可以持续跟踪共有多少个对象指向某笔资源,并在无人指向它是自动删除该资源。
void f()
{
std:: shared_ptr<investment> plv1(createinvestment());//pInv1指向createInvestment()返回物;
std:: shared_ptr<investment> plv2(plv1);//pInv1,pInv2指向同一个对象;
plv1 = plv2;//同上,无变化
}//函数退出,pInv1,pInv2被销毁,它们所指的对象也竟被自动释放。
还有一个问题就是,上面两个智能指针 auto_ptr 与 shared_ptr在析构函数内只执行 delete 而不是delete[] ,也就意味着,在动态分配的数组上这两个指针也存在风险。这个可能就需要使用boost:: shared_array来帮助了。
记住:
为防止资源泄露,请使用RAII对象,他们在构造函数中获得资源,在析构函数中释放资源。
两个比较常用的RAII类分别是auto_ptr和shared_ptr.后者通常都是较佳选择,因为其拷贝比较直观。
2、 在资源管理类中小心拷贝行为
在堆上申请的资源我们可以用上面的智能指针类去管理,但有些并不适合。这时,我们就需要建立自己的资源管理类。
void lock(Mutex *pm); //锁定pm所指的互斥量
void unlock(Mutex *pm); //将pm解除锁定
// 我们建立的资源管理类可能会是这样:
class Lock
{
public:
explicit Lock(Mutex *pm)
: mutexPtr(pm)
{
lock(mutexPtr);
}
~Lock()
{
unlock(mutexPtr);
}
private:
Mutex *mutexPtr;
};
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
当Lock对象被复制,会发生什么?
通常,我们会选择以下两种解决方案:
1、禁止复制
2、对底层资源使用 引用计数法
通常只要内含一个tr1::shared_ptr成员变量,RAII类便可实现”引用计数“行为。
class Lock
{
public:
explicit Lock(Mutex *pm)
: mutexPtr(pm, unlock) //由于tr1::shared_ptr缺省行为是”当引用计数为0时删除其所指物“,幸运的是 //我们可以指定”引用计数“为9时被调用的所谓”删除器“,即第二个参数unlock
{
lock(mutexPtr.get());
}
private:
std::tr1::shared_ptr<Mutex> mutexPtr;
};
本例中,并没说明析构函数,因为没有必要。编译器为我们生成的析构函数会自动调用其non-static成员变量(mutexPtr)的析构函数。而mutexPtr的析构函数会在互斥量”引用计数“为0时自动调用tr1::shared_ptr的删除器(unlock)。
Copying函有可能被编译器自动创建出来,因此除非编译器所生成版本做了你想要做的事,否则你得自己编写它们。
记住:
- 复制RAII对象必须一并复制它所管理的资源,所以资源的copying行为决定RAII对象的copying行为。
- 普遍而常见的RAII类拷贝行为是:抑制拷贝,施行引用计数法。不过其它行为也可能被实现。
Effective C++ 条款13/14 以对象管理资源 || 在资源管理类中小心拷贝行为的更多相关文章
- Effective C++ -----条款13:以对象管理资源
为防止资源泄漏,请使用RAII(Resource Acquisiton Is Initialization) 对象,它们在构造函数中获得资源并在析构函数中释放资源. 两个常被使用的RAII class ...
- 条款13:以对象管理资源(use objects to manage resources)
NOTE: 1.为防止资源泄漏,请使用RAII对象,它们在构造函数中获得资源并在析构函数中释放资源. 2.两个常被使用的RAII classes 分别是 trl::shared_ptr 和 auto_ ...
- effective C++ 读书笔记 条款14 以对象管理资源
如果我们使用一个投资行为的程序库: #include "stdafx.h" #include <iostream> #include <memory> us ...
- Effective C++(14) 在资源管理类中小心copying行为
问题聚焦: 上一条款所告诉我们的智能指针,只适合与在堆中的资源,而并非所有资源都是在堆中的. 这时候,我们可能需要建立自己的资源管理类,那么建立自己的资源管理类时,需要注意什么呢?. ...
- [Effective C++ --014]在资源管理类中小心copying行为
第一节 <背景> 条款13中讲到“资源取得的时机便是初始化时机”并由此引出“以对象管理资源”的概念.通常情况下使用std中的auto_ptr(智能指针)和tr1::shared_ptr(引 ...
- 【14】在资源管理类中小心copying行为
1.为什么要使用资源管理类? 资源管理类的思路就是,栈上的对象,封装堆上分配的资源,确保一定会释放资源.auto_ptr和shared_ptr就是资源管理类,行为上像指针. 2.auto_ptr和sh ...
- EC笔记:第三部分:13、以对象管理资源
C++相比Java等含有gc的语言来说,内存管理方面(也包括资源管理)比较令人头疼.一些初级程序员,甚至是一些经验丰富的老程序员,也会经常在资源管理上犯错.这时候就需要一个能够自动管理资源的东西(gc ...
- 条款14:在资源管理类中小心copying行为
请牢记: 1.复制RAII对象必须一并复制它所管理的资源,所以资源的copying行为决定RAII对象的copying行为. 2.普遍常见的RAII class copying行为是:抑制copyin ...
- EC笔记:第三部分:14、在资源管理类中小心Copying行为
场景 上一节实现了智能指针,其中的拷贝构造函数和赋值运算符是通过增加/减少指针的引用计数来操作的.但是如果是管理一个独占资源呢?我们希望在一个资源使用时被锁定,在使用完毕后被释放. #include ...
随机推荐
- ACM训练联盟周赛 K. Teemo's reunited
Teemo likes to drink raspberry juice. He even spent some of his spare time tomake the raspberry jui ...
- “程序设计与算法训练”课程设计:“BP神经网络的实现”(C++类封装实现)
一 题目: 71 BP神经网络的实现: 利用C++语言实现BP神经网络, 并利用BP神经网络解决螨虫分类问题: 蠓虫分类问题:对两种蠓虫(A与B)进行鉴别,依据的资料是触角和翅膀的长度,已知了9支Af ...
- xshell连接linux
一些命令和快捷键: Ctrl + Alt 切换linux和windows的鼠标 Ctrl + c 或 Ctrl + d退出>状态 在xshell终端输入exit,退出与linux服务器的连接 登 ...
- linux无人值守安装介绍(一)
一.术语解释 PXE(Pre-boot ExecutionEnvironment)是由Intel设计的协议,它可以使计算机通过网络而不是从本地硬盘.光驱等设备启动.现代的网卡,一般都内嵌支持PXE的R ...
- python3--__getattr__和__setattr__捕捉属性的一个引用
__getattr__和__setattr__捕捉属性的一个引用 __getattr__方法是拦截属性点号运算.更确切地说,当通过对未定义(不存在)属性名称和实例进行点号运算时,就会用属性名称为字符串 ...
- Centos6.5搭建git远程仓库
远程仓库搭建 step1:安装git ```yum -y install git``` step2:创建用户git,用来运行git服务 useradd git passwd git //修改git用户 ...
- 2017ACM/ICPC广西邀请赛-重现赛(感谢广西大学)
上一场CF打到心态爆炸,这几天也没啥想干的 A Math Problem Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/3 ...
- EXPDP/IMPDP任务的查看与管理
EXPDP/IMPDP相比传统的exp/imp的最本质区别在于服务器端执行,客户端发出指定后,通过API启动服务器的备份job,在执行过程中,可以拿下Ctrl+C组合键,退出当前交互模式,退出之后,导 ...
- POJ 1067: Wythoff Game【博弈】
经典的威佐夫博奕把黄金分割常数乘以k(k=m-n)即为奇异点,此时奇异点是用小数据观察出来的,具体的数学证明,观察到黄金分割常数是无理数,再加上高斯函数[kφ]的形势将自然数分割成两个等价类很容易想到 ...
- 刷题总结——bzoj1725(状压dp)
题目: 题目描述 Farmer John 新买了一块长方形的牧场,这块牧场被划分成 N 行 M 列(1<=M<=12; 1<=N<=12),每一格都是一块正方形的土地. FJ ...