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

条款13:以对象管理资源

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

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++笔记03:资源管理的更多相关文章

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

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

  2. Effective C++ 笔记三 资源管理

    条款13:以对象管理资源 许多资源被动态分配于heap内而后被用于单一区块或函数内.它们应该在控制流离开那个区块或函数时被释放.标准程序库提供的auto_ptr正是针对这种形式而设计的特制产品.aut ...

  3. Effective Java笔记一 创建和销毁对象

    Effective Java笔记一 创建和销毁对象 第1条 考虑用静态工厂方法代替构造器 第2条 遇到多个构造器参数时要考虑用构建器 第3条 用私有构造器或者枚举类型强化Singleton属性 第4条 ...

  4. 《30天自制操作系统》笔记(03)——使用Vmware

    <30天自制操作系统>笔记(03)——使用Vmware 进度回顾 在上一篇,实现了用IPL加载OS程序到内存,然后JMP到OS程序这一功能:并且总结出下一步的OS开发结构.但是遇到了真机测 ...

  5. [Effective JavaScript 笔记] 第4条:原始类型优于封闭对象

    js有5种原始值类型:布尔值.数字.字符串.null和undefined. 用typeof检测一下: typeof true; //"boolean" typeof 2; //&q ...

  6. [Effective JavaScript 笔记] 第5条:避免对混合类型使用==运算符

    “1.0e0”=={valueOf:function(){return true;}} 是值是多少? 这两个完全不同的值使用==运算符是相等的.为什么呢?请看<[Effective JavaSc ...

  7. [Effective JavaScript 笔记]第3章:使用函数--个人总结

    前言 这一章把平时会用到,但不会深究的知识点,分开细化地讲解了.里面很多内容在高3等基础内容里,也有很多讲到.但由于本身书籍的篇幅较大,很容易忽视对应的小知识点.这章里的许多小提示都很有帮助,特别是在 ...

  8. [Effective JavaScript 笔记]第27条:使用闭包而不是字符串来封装代码

    函数是一种将代码作为数据结构存储的便利方式,代码之后可以被执行.这使得富有表现力的高阶函数抽象如map和forEach成为可能.它也是js异步I/O方法的核心.与此同时,也可以将代码表示为字符串的形式 ...

  9. [Effective JavaScript 笔记]第28条:不要信赖函数对象的toString方法

    js函数有一个非凡的特性,即将其源代码重现为字符串的能力. (function(x){ return x+1 }).toString();//"function (x){ return x+ ...

随机推荐

  1. CVE-2013-3346Adobe Reader和Acrobat 内存损坏漏洞分析

    [CNNVD]Adobe Reader和Acrobat 内存损坏漏洞(CNNVD-201308-479) Adobe Reader和Acrobat都是美国奥多比(Adobe)公司的产品.Adobe R ...

  2. C++之客户消费积分管理系统

    之前数据结构课程设计要求做这么一个小程序,现在贴上源码,来和大家进行交流学习,希望大家给出意见和建议 程序以链表为主要数据结构对客户信息进行存储,对身份证号码判断了位数及构成(前十七位为数字,最后一位 ...

  3. Asp.net Vnext 调试源码

    概述 本文已经同步到<Asp.net Vnext 系列教程 >中] 如果想对 vnext深入了解,就目前为止太该只有调试源码了 实现 github上下载源码 选择对应的版本,版本错了是不行 ...

  4. drools7 (三、kmodule 介绍)

    注意几点: 1. kmodule 有默认的加载路径, 看  KieModuleModelImpl 这个类的源代码 public class KieModuleModelImpl implements ...

  5. chromiumFx编译使用

    CEF chormeFx 为针对.Net的CEF框架,下载链接为: https://bitbucket.org/chromiumfx/chromiumfx 点击Download可以下载chromium ...

  6. ecshop用户中心菜单选项显示内容标签

    ecshop用户中心菜单选项有了,那肯定需要给相应的菜单选项添加内容,下面我们主要来讲下调用内容的标签,你也可以先访问一下用户中心菜单选项修改. 用户中心页面的内容分布在两个模板文件中:user_cl ...

  7. 用户管理和FTP服务配置

    批量创建用户 python脚本:creuser.py import osulist=open('usernames','r')for x in ulist: cmd="useradd -g ...

  8. vue.js-过滤器 filters使用详细示例

    什么也不说了,直接上干货: 1.首先,获取后台数据到页面,并调用过滤器 在<script>中添加 onRefreshItems (currentPage, perPage) { if (t ...

  9. tomcat如何利用waf进行防护

    近期某一实验室遇到一个问题:web环境是windows+tomcat+mysql,检测到cookie注入,此时又不想修改代码.此时两种方案进行解决: 1.利用安软(waf)类进行检测防御.这里国内主要 ...

  10. 第2天:Django路由与视图

    在应用中创建视图定义路由 配置文件说明 静态文件使用 Django解析路由的流程 路由顺序 路由命名与reverse反推 在应用中创建视图定义路由 前面我们已经创建了子应用users,但是这个user ...