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)直接访问原始资源 ...
随机推荐
- SpringMVC结合ajaxfileupload.js实现文件无刷新上传
直接看代码吧,注释都在里面 首先是web.xml <?xml version="1.0" encoding="UTF-8"?> <web-ap ...
- [HIHO1041]国庆出游(DFS, bitset)
题目链接:http://hihocoder.com/problemset/problem/1041 学会了用C++的bitset哈,可喜可贺.以后遇到超过64位想用位来表示状态就不愁了哈. 这题用bi ...
- Mybatis传递多个参数
方法一: //DAO层的函数方法Public User selectUser(String name,String area); 对应的Mapper.xml <select id="s ...
- SQL group by分组查询(转)
本文导读:在实际SQL应用中,经常需要进行分组聚合,即将查询对象按一定条件分组,然后对每一个组进行聚合分析.创建分组是通过GROUP BY子句实现的.与WHERE子句不同,GROUP BY子句用于归纳 ...
- Linux Autotools
/********************************************************************** * Linux Autotools * 说明: * 我们 ...
- LeetCode Binary Tree Maximum Path Sum 二叉树最大路径和(DFS)
题意:给一棵二叉树,要求找出任意两个节点(也可以只是一个点)的最大路径和,至少1个节点,返回路径和.(点权有负的.) 思路:DFS解决,返回值是,经过从某后代节点上来到当前节点且路径和最大的值.要注意 ...
- acdream 1683 村民的怪癖(KMP,经典变形)
Problem Description 娜娜费劲九牛二虎之力终于把糖果吃完了(说好的吃不完呢?骗人,口亨~),于是,缘溪行,忘路之远近.忽逢桃花林,夹岸数百步,中无杂树,芳草鲜美,落英缤纷,娜娜甚异之 ...
- 浅析extendedLayout, automaticallyAdjustsScrollViewInsets, extendedLayoutIncludesOpaqueBars
参考文章: http://stackoverflow.com/questions/18798792/explaining-difference-between-automaticallyadjusts ...
- HDU 2026 首字母变大写
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; int ma ...
- UVa 11520 Fill the Square 填充正方形
在一个 n * n 网格中填了一些大写字母,你的任务是把剩下的格子中也填满大写字母,使得任意两个相邻格子(即有公共边的格子)中的字母不同.如果有多重填法,则要求按照从上到下,从左到右的顺序把所有格子连 ...