资源:动态分配的内存、文件描述器、互斥锁、图形界面中的字型与笔刷、数据库连接以及网络sockets等,无论哪一种资源,重要的是,当你不再使用它时,必须将它还给系统。

条款13:以对象管理资源

当我们向系统申请资源后,一定要记得释放,不然就容易发生内存泄漏。但是意识到这样一件事并不是很容易,比如我们是通过一个函数来动态分配内存并返回一个指针。

Investment* ceateInvestment();// 返回指针,指向动态分配对象
void f()
{
Investment* pInv = ceateInvestment();
// ...
delete pInv;
}

即使像上面的代码一样,我们在用完指针pInv后,我们调用了delete,但是还是可能出问题,有时候我们可能在...的部分提前return或跳出了循环,甚至在该部分发生了异常,这都导致delete根本执行不到。

解决方法是我们把指针放在一个资源管理的类里,让类对象在生命结束的时候,会自动调用析构函数,而析构函数里会执行delete。

两个常被使用的RAII类分别是:shared_ptr和unique_ptr,它们间不同的是shared_ptr允许存在同一内存区域的多个指针拷贝,而unique_ptr只允许一份指针指向对象,当uniuqe_ptr发生赋值操作时,用于赋值的指针将会变成null。

条款14:在资源管理类中小心copying行为

在实际管理资源时,并非所有的资源都是堆内存(heap),所以unique_ptr或shared_ptr这样的智能指针往往不适合作为资源管理者。

比如你需要控制类型为Mtux的互斥器对象,共有lock和unlock两函数可用,你需要保证的就是不要忘记将一个被锁住的Mutex解锁,我们的想法的主旨就是:资源在构造期间创建,在析构期间释放。

class Lock
{
public:
explicit Lock(Mutex* pm) :mutexPtr(pm){ lock(mutexPtr;) }// 获得资源
~Lock(){ unlock(mutexPtr); }// 释放资源
};

这样虽然很好,但是如果Lock被复制了,就会发生问题。它可能会引起对了一Mutex解锁两次。

常见的解决方案有2种:一种是禁止复制;第二种是对底层资源祭出“引用计数法”,这也是shared_ptr实现原理。

条款15:在资源管理类中提供对原始资源的访问

很多API接口往往要求访问原始资源,所以每一个RAII class应该提供一个“取得其所管理之资源”的办法,比如提供一个get函数。

对原始资源的访问可能经由显式转换或隐式转换。一般而言显式转换比较安全,但隐式转换对客户比较方便。

条款16:成对使用new和delete时要采用相同形式

如果你在new表达式中使用[],必须在相应的delete表达式中使用[]。如果你在new表达式中不使用[],一定不要在相应的delete表达式中使用[]。

string* stringPtr1 = new string;
string* stringPtr2 = new string[100];
delete stringPtr1; // 删除一个对象
delete[] stringPtr2; // 删除一个由对象组成的数组

条款17:以独立语句将newed对象置入智能指针

假设我们有个函数用来控制程序的优先权,另一个函数用来在某个动态分配所得到的Wieget上进行某些带有优先权的处理:

int priority();
void processWidget(shared_ptr<Widget>pw, int priority);

现在假如我们这样调用它:

processWidget(share_ptr<Widget>(new Widget),priotrity());

在调用processWidget之前,编译器必须创建代码,做以下三件事:

  • 调用priority
  • 执行”new Widget”
  • 调用shared_ptr构造函数

C++编译器并不保证上次代码执行的次序,但有一点可以保证,那就是new Widget肯定发生成share_ptr构造函数之前。

假如priority发生在第二步,并且执行过程中发生了异常,那就有可能资源不能正常的释放。

避免这种情况,就需要使用分离语句,先创建Widget,然后再将它置入一个智能指针内,然后再把那个智能指针传给processWidget。

【Effective C++】资源管理的更多相关文章

  1. Effective C++ ——资源管理

    条款13:以对象来管理资源 在C++中我们经常会涉及到资源的申请与申请,一般都是由关键字new 和 delete来操作的,两者都是成对存在的,缺一不可,否则会出现意想不到的问题,例如: class I ...

  2. Effective C++ —— 资源管理(三)

    条款13 : 以对象管理资源 假设有如下代码: Investment* createInvestment(); //返回指针,指向Investment继承体系内的动态分配对象,调用者有责任删除它 vo ...

  3. C++笔记--thread pool【转】

    版权声明:转载著名出处 https://blog.csdn.net/gcola007/article/details/78750220 背景 刚粗略看完一遍c++ primer第五版,一直在找一些c+ ...

  4. c++内存管理学习纲要

    本系列文章,主要是学习c++内存管理这一块的学习笔记. 时间:6.7-21 之下以技术内幕的开头语,带入到学习C++内存管理的技术中吧: 内存管理是C++最令人切齿痛恨的问题,也是C++最有争议的问题 ...

  5. Effective C++(15) 在资源管理类中提供对原始资源的访问

      问题聚焦:     资源管理类是为了对抗资源泄露.     如果一些函数需要访问原始资源,资源管理类应该怎么做呢?        关于资源管理的概念总是显得那么的高大上,其实只是抽象一点. 下面用 ...

  6. Effective C++(14) 在资源管理类中小心copying行为

    问题聚焦:     上一条款所告诉我们的智能指针,只适合与在堆中的资源,而并非所有资源都是在堆中的.     这时候,我们可能需要建立自己的资源管理类,那么建立自己的资源管理类时,需要注意什么呢?. ...

  7. 《Effective C++》第3章 资源管理(2)-读书笔记

    章节回顾: <Effective C++>第1章 让自己习惯C++-读书笔记 <Effective C++>第2章 构造/析构/赋值运算(1)-读书笔记 <Effecti ...

  8. 《Effective C++》第3章 资源管理(1)-读书笔记

    章节回顾: <Effective C++>第1章 让自己习惯C++-读书笔记 <Effective C++>第2章 构造/析构/赋值运算(1)-读书笔记 <Effecti ...

  9. Effective C++笔记:资源管理

    资源:动态分配的内存.文件描述器.互斥锁.图形界面中的字型与笔刷.数据库连接以及网络sockets等,无论哪一种资源,重要的是,当你不再使用它时,必须将它还给系统. 条款13:以对象管理资源 当我们向 ...

  10. [Effective C++ --015]在资源管理类中提供对原始资源的访问

    引言 资源管理类是防止资源泄漏的有力武器,但是许多APIs直接指涉资源,除非你发誓永不使用这样的APIs,否则只得绕过资源管理对象(resource-managing objects)直接访问原始资源 ...

随机推荐

  1. AC日记——最优贸易 codevs 1173

    题目描述 Description [问题描述]C 国有n 个大城市和m 条道路,每条道路连接这n 个城市中的某两个城市.任意两个城市之间最多只有一条道路直接相连.这m 条道路中有一部分为单向通行的道路 ...

  2. django中表变更后migrate无效的问题

    问题描述: 已有的model,修改之后,想重新建模,于是将migrations文件夹中除__init__.py之外其他文件都删掉,再次执行以下步骤python manage.py makemigrat ...

  3. CentOS6.7源码安装MySQL5.6

    1.源码安装MySQL5.6 # CentOS6操作系统安装完成后,默认会在/etc目录下存在一个my.cnf, # 强制卸载了mysql-libs之后,my.cnf就会消失 rpm -qa | gr ...

  4. 提高速度 history 的利用

    history的介绍history是shell的内置命令,其内容在系统默认的shell的man手册中.history是显示在终端输入并执行的过命令,系统默认保留1000条.[root@localhos ...

  5. Delphi Helper Record Class

    unit Unit1; {$DEFINE USESGUIDHELP} interface implementation {$IFDEF USESGUIDHELP} uses System.SysUti ...

  6. 通过HTML5 FileReader实现上传图片预览功能

    原文:http://www.htmleaf.com/ziliaoku/qianduanjiaocheng/201706224590.html 在上传图片到服务器之前,我们希望可以预览一下要上传的图片. ...

  7. 如何让你的服务屏蔽Shodan扫描

    1. 前言 在互联网中,充斥着各种各样的网络设备,shodan等搜索引擎提供给了我们一个接口,让我们可以在输入一些过滤条件就可以检索出网络中相关的设备. 对于我们的一些可能有脆弱性或者比较隐私的服务, ...

  8. 全方位绕过软WAF攻略

    0×00 前言 现在软waf较为多,就在今年夏天苦逼挖洞的日子里经常遇到360主机卫士,安全狗,云锁之类的软waf进行拦截,经常碰到如下拦截提示: 看到以上三个拦截提示就让人头疼不已,欲罢不能. so ...

  9. Frotinet60D IP映射 開放指定端口是實際應用

    有多個外網IP的環境中,在某一部電腦上,如何使用多個外網IP中的某一個?且為使用的Bitcomet開放TCP,TUP特定端口? 1.在本機windows防火墻中"輸入" 和&quo ...

  10. Leet Code OJ 338. Counting Bits [Difficulty: Medium]

    题目: Given a non negative integer number num. For every numbers i in the range 0 ≤ i ≤ num calculate ...