effective c++:资源管理
对象管理资源
createInvestment 函数作用时创建一个invest对象:
- void f()
- {
- Investment *pInv = createInvestment(); // call factory function
- ... // use pInv
- delete pInv; // release object
- }
既然f函数中创建对象,销毁对象的责任也应该由它来承担,但是如果“……”区域出现异常或return提前执行,delete将被跳过,从而造成严重的内存泄露,为了确保无论发生什么情况createInvestment返回的对象始终能记得被销毁,我们就需要将他放入一个对象内,析构函数会自动的释放资源,c++标准库提供auto_ptr,即智能指针,他是个类指针对象,析构函数自动对他调用delete:
- void f()
- {
- std::auto_ptr<Investment> pInv(createInvestment()); // call factory
- // function
- ... // use pInv as
- // before
- } // automatically
- // delete pInv via
- // auto_ptr’s dtor
在使用auto_ptr时要注意,一旦让多个auto_ptr指向同一个对象,资源只存放在最后指向的指针中,其他指针均为null,所以auto_ptr在实际使用时局限性很大,c++11已经舍弃了这一智能指针,他的替代方案时shared_ptr,它能够持续的跟踪共有多少个对象指向资源,在无人指向资源时才删除该资源,但是由于shared_ptr在析构函数中使用的是delete而不是delete[],对于动态分配的数组显然不可取,针对动态数组的智能指针在c++11中并没有提供,但在幸运的事boost中有我们想要的boost::scoped_array和boost::shared_array,google c++ sytle中建议需要使用智能指针的话尽量使用scoped_ptr,只在非常特定的情况下使用 std::tr1::shared_ptr, 例如 STL 容器中的对象。“智能” 指针看上去是指针, 其实是附加了语义的对象. 以 scoped_ptr 为例, scoped_ptr 被销毁时, 它会删除所指向的对象. shared_ptr 也是如此, 并且 shared_ptr 实现了引用计数, 所以最后一个 shared_ptr 对象析构时, 如果检测到引用次数为 0,就会销毁所指向的对象。一般来说,我们倾向于设计对象隶属明确的代码, 最明确的对象隶属是根本不使用指针, 直接将对象作为一个作用域或局部变量使用. 另一种极端做法是, 引用计数指针不属于任何对象. 这种方法的问题是容易导致循环引用, 或者导致某个对象无法删除的诡异状态, 而且在每一次拷贝或赋值时连原子操作都会很慢。
假如将shared_ptr用在互斥器中(mutex objects)
- class Lock {
- public:
- explicit Lock(Mutex *pm)
- : mutexPtr(pm)
- { lock(mutexPtr); } // acquire resource
- ~Lock() { unlock(mutexPtr); } // release resource
- private:
- Mutex *mutexPtr;
- };
shared_ptr缺省时将引用次数为0时删除所指物,然而在Mutex中,我们要做的释放动作时解锁而不是删除,这就要用到shared_ptr中的删除器来指定代替默认状态下的删除操作,本例中引用计数为0时则自动调用unlock函数
- class Lock {
- public:
- explicit Lock(Mutex *pm) // init shared_ptr with the Mutex
- : mutexPtr(pm, unlock) // to point to and the unlock func
- { // as the deleter†
- lock(mutexPtr.get()); // see Item15 for info on “get”
- }
- private:
- std::tr1::shared_ptr<Mutex> mutexPtr; // use shared_ptr
- };
new与智能指针
假设我们有一个函数来解释处理程序的优先权,另一个函数用来动态分配Widge上进行某些优先权处理:
- int priority();
- void processWidget(std::tr1::shared_ptr<Widget> pw, int priority);
processWidge决定动态分配得来的Widge运用智能指针
- processWidget(std::tr1::shared_ptr<Widget>(new Widget), priority());
虽然这里使用了智能指针,但还是会有泄露的发生。
实际参数("std::tr1::shared_ptr<Widget>(new Widget)"),由两部分组成:new Widge表达式和shared_ptr构造函数,但是c++编译器的运行次序可不是按照参数次序来执行,对于priority的调用可能会在new Widge表达式和shared_ptr构造函数两个操作的之前,中间,最后执行,问题在于如果非常不巧的priority在第一个实参的两个操作之间执行,又非常不幸priority调用时抛出异常:
- . Execute “new Widget”.
- . Call priority.
- . Call the tr1::shared_ptr constructor.
第一个new操作的建立 的资源将没有办法回收。
避免这一问题的办法是分离语句,明确调用顺序
- std::tr1::shared_ptr<Widget> pw(new Widget); // store newed object
- // in a smart pointer in a
- // standalone statement
- processWidget(pw, priority()); // this call won’t leak
effective c++:资源管理的更多相关文章
- Effective C++ ——资源管理
条款13:以对象来管理资源 在C++中我们经常会涉及到资源的申请与申请,一般都是由关键字new 和 delete来操作的,两者都是成对存在的,缺一不可,否则会出现意想不到的问题,例如: class I ...
- Effective C++ —— 资源管理(三)
条款13 : 以对象管理资源 假设有如下代码: Investment* createInvestment(); //返回指针,指向Investment继承体系内的动态分配对象,调用者有责任删除它 vo ...
- C++笔记--thread pool【转】
版权声明:转载著名出处 https://blog.csdn.net/gcola007/article/details/78750220 背景 刚粗略看完一遍c++ primer第五版,一直在找一些c+ ...
- c++内存管理学习纲要
本系列文章,主要是学习c++内存管理这一块的学习笔记. 时间:6.7-21 之下以技术内幕的开头语,带入到学习C++内存管理的技术中吧: 内存管理是C++最令人切齿痛恨的问题,也是C++最有争议的问题 ...
- Effective C++(15) 在资源管理类中提供对原始资源的访问
问题聚焦: 资源管理类是为了对抗资源泄露. 如果一些函数需要访问原始资源,资源管理类应该怎么做呢? 关于资源管理的概念总是显得那么的高大上,其实只是抽象一点. 下面用 ...
- Effective C++(14) 在资源管理类中小心copying行为
问题聚焦: 上一条款所告诉我们的智能指针,只适合与在堆中的资源,而并非所有资源都是在堆中的. 这时候,我们可能需要建立自己的资源管理类,那么建立自己的资源管理类时,需要注意什么呢?. ...
- 《Effective C++》第3章 资源管理(2)-读书笔记
章节回顾: <Effective C++>第1章 让自己习惯C++-读书笔记 <Effective C++>第2章 构造/析构/赋值运算(1)-读书笔记 <Effecti ...
- 《Effective C++》第3章 资源管理(1)-读书笔记
章节回顾: <Effective C++>第1章 让自己习惯C++-读书笔记 <Effective C++>第2章 构造/析构/赋值运算(1)-读书笔记 <Effecti ...
- Effective C++笔记:资源管理
资源:动态分配的内存.文件描述器.互斥锁.图形界面中的字型与笔刷.数据库连接以及网络sockets等,无论哪一种资源,重要的是,当你不再使用它时,必须将它还给系统. 条款13:以对象管理资源 当我们向 ...
- [Effective C++ --015]在资源管理类中提供对原始资源的访问
引言 资源管理类是防止资源泄漏的有力武器,但是许多APIs直接指涉资源,除非你发誓永不使用这样的APIs,否则只得绕过资源管理对象(resource-managing objects)直接访问原始资源 ...
随机推荐
- Go语言学习笔记一(语法篇)
国庆节七天假期,这段时间刚好项目那边催的不是很紧,基本上每天都是白天重构一下项目代码,晚上自己学习.(大概是因为容总那边的人都去度假了把项目进度放慢了吧.这两天“彩虹”姐姐也来凑热闹,据说还是直接从澳 ...
- BZOJ 1507 Editor(块状链表)
题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1507 题意:一个文本编辑器,模拟以下操作: 思路:块状链表的主要操作: (1)find( ...
- SPOJ 2916 Can you answer these queries V(线段树-分类讨论)
题目链接:http://www.spoj.com/problems/GSS5/ 题意:给出一个数列.每次查询最大子段和Sum[i,j],其中i和j满足x1<=i<=y1,x2<=j& ...
- Model Browser
http://www.entityframeworktutorial.net/model-browser-in-entity-framework.aspx We have created our fi ...
- find a filename from a filehandle in Perl
my $filename='/tmp/tmp.txt';open my $fh, '>', $filename;my $fd = fileno $fh;print readlink(" ...
- HTTP 请求方式: GET和POST的比较
GET和POST是HTTP的两个常用方法. 什么是HTTP? 超文本传输协议(HyperText Transfer Protocol -- HTTP)是一个设计来使客户端和服务器顺利进行通讯的协议 ...
- bzoj1564: [NOI2009]二叉查找树
dp. 首先这棵树是一个treap. 权值我们可以改成任意实数,所以权值只表示相互之间的大小关系,可以离散化. 树的中序遍历是肯定确定的. 用f[l][r][w]表示中序遍历为l到r,根的权值必须大于 ...
- BZOJ 4269 再见Xor
线性基. 求次大值就是再异或一个线性基好了. #include<iostream> #include<cstdio> #include<cstring> #defi ...
- Jave 鼠标点击画太极 PaintTaiji (整理)
package demo; /** * Jave 鼠标点击画太极 PaintTaiji (整理) * 声明: * 又是一份没有注释的代码,而且时间已经久远了,不过代码很短,解读起来应该 * 不会很麻烦 ...
- 2012年7月12 – 腾讯公司 WEB高级应用开发工程师 最新面试题 [转]
笔试(45 minute):(本来是四张纸,被我弄丢了一张!无伤大雅,难度级别不会有出入) 注意:由于时间紧迫和水平有限,难免有不足或错误,请指证,虚心学习! [PHP] 写出PHP中至少5个全局变量 ...