条款 13 :以对象管理资源

例:
     voidf()
     { 
         Investment *pInv = createInvestment(); 
         ...                  //这里存在诸多“不定因素”,可能造成delete pInv;得不到执行,这可能就存在潜在的内存泄露。
         delete pInv;
     }

 解决方法:把资源放进对象内,我们便可依赖C++的“析构函数自动调用机制”确保资源被释放。
    许多资源被动态分配于堆内而后被用于单一区块或函数内。它们应该在控制流离开那个区块或函数时被释放。标准

程序库提供的auto_ptr正是针对这种形势而设计的特制产品。auto_ptr是个“类指针对象”,也就是所谓的“智能指针”,

其析构函数自动对其所指对象调用delete。

void f()
     { 
        std::auto_ptr<Investment> pInv(createInvestment()); 
         ... 
     }         //函数退出,auto_ptr调用析构函数自动调用delete,删除pInv;无需显示调用delete。

“以对象管理资源”的两个关键想法:

  • 获得资源后立刻放进管理对象内(如auto_ptr)。每一笔资源都在获得的同时立刻被放进管理对象中。“资源取得时机便是初始化时机”(Resource Acquisition Is Initialization;RAII)。
  • 管理对象运用析构函数确保资源被释放。即一旦对象被销毁,其析构函数被自动调用来释放资源。

由于auto_ptr被销毁时会自动删除它所指之物,所以不能让多个auto_ptr同时指向同一对象。所以auto_ptr若通

过copying函数复制它们,它们会变成NULL,而复制所得的指针将取得资源的唯一拥有权!

看下面例子:

std::auto_ptr<Investment> pInv1(createInvestment()); //pInv1指向createInvestment()返回物;
     std::auto_ptr<Investment>pInv2(pInv1);                     //现在pInv2指向对象,而pInv1被设为NULL;

pInv1 = pInv2;                                                           //现在pInv1指向对象,而pIn2被设为NULL;

受auto_ptr管理的资源必须绝对没有一个以上的auto_ptr同时指向它。即“有你没我,有我没你”。
      auto_ptr的替代方案是“引用计数型智能指针”(reference-counting smart pointer;SCSP)、它可以持续跟踪共有

多少对象指向某笔资源,并在无人指向它时自动删除该资源。

TR1的tr1::shared_ptr就是一个"引用计数型智能指针"。
     void f()
     { 
         ... 
        std::tr1::shared_ptr<Investment>  pInv1(createInvestment()); //pInv1指向createInvestment()返回物;
        std::tr1::shared_ptr<Investment> pInv2(pInv1);                    //pInv1,pInv2指向同一个对象;
         pInv1 = pInv2;                                                                     //同上,无变化
         ... 
     }        //函数退出,pInv1,pInv2被销毁,它们所指的对象也竟被自动释放。
       auto_ptr和tr1::shared_ptr都在其析构函数内做delete而不是delete[],也就意味着在动态分配而得的数组身上使

用auto_ptr或tr1::shared_ptr是个潜在危险,资源得不到释放。也许boost::scoped_array和boost::shared_array能提供

帮助。还有,vector和string几乎总是可以取代动态分配而得的数组。

请记住:

  • 为防止资源泄漏,请使用RAII对象,它们在构造函数中获得资源并在析构函数中释放资源。
  • 两个常被使用的RAII类分别是auto_ptr和tr1::shared_ptr。后者通常是较佳选择,因为其拷贝行为比较直观。若选择auto_ptr,复制动作会使他(被复制物)指向NULL。

《Effective C++》学习笔记条款13 以对象管理资源的更多相关文章

  1. effective C++ 读书笔记 条款14 以对象管理资源

    如果我们使用一个投资行为的程序库: #include "stdafx.h" #include <iostream> #include <memory> us ...

  2. Effective C++(13) 用对象管理资源

    问题聚焦: 从这条准则开始,都是关于资源管理的. 资源,一旦用了它,将来必须还给系统. 本条准则,基于对象的资源管理办法,建立在C++的构造函数,析构函数和拷贝函数(拷贝构造函数和重载赋值操作符)的基 ...

  3. Effective C++学习笔记 条款04:确定对象被使用前已先被初始化

    一.为内置类型对象进行手工初始化,因为C++不保证初始化它们. 二.对象初始化数据成员是在进入构造函数用户编写代码前完成,要想对数据成员指定初始化值,那就必须使用初始化列表. class A { pu ...

  4. Effective C++学习笔记 条款07:为多态基类声明virtual析构函数

    一.C++明确指出:当derived class对象经由一个base class指针被删除,而该base class带着一个non-virtual析构函数,其结果未定义——实际执行时通常发生的是对象的 ...

  5. Effective C++学习笔记 条款02:尽量以const,enum,inline替换 #define

    尽量使用const替换 #define定义常量的原因: #define 不被视为语言的一部分 宏定义的常量,预处理器只是盲目的将宏名称替换为其的常量值,导致目标码中出现多分对应的常量,而const定义 ...

  6. Effective Java学习笔记--创建和销毁对象

    创建和销毁对象 一.静态工厂方法代替构造器 静态工厂方法的优缺点 优点: 1.可以自定义名称(可以将功能表述的更加清晰) 2.不必每次调用都创建新的对象(同一对象重复使用) 3.返回的类型可以是原返回 ...

  7. Effective C++学习笔记 条款06:如不想使用编译器自动生成的函数,就该明确拒绝

    一.为驳回编译器自动提供的机能,可将相应成员函数声明为private并且不予实现.(如果你仅仅是自己不实现的话,编译器会帮你实现) 如: class A { public: A(const strin ...

  8. Effective C++学习笔记 条款05:了解C++默默编写并调用的哪些函数

    一.如果用户没有提供构造函数.copy构造函数.copy assignment操作符和析构函数,当且仅当这些函数被需要的时候,编译器才会帮你创建出来.编译器生成的这些函数都是public且inline ...

  9. Linux学习笔记(13)权限管理

    1 ACL权限 (1)简介和开启方式 ACL(Access Control List)权限的目的是在提供传统的owner.group.others的read.write.execute权限之外的局部权 ...

随机推荐

  1. 新浪微博登录接口(PHP版)

    CI框架下 新浪微博登录接口完整版说明:本贴只适合CI框架.功能实现:登录接口跳转链接成功,获取用户信息(包括最重要的u_id)成功,将用户与本地平台连接起来,用户登录成功后信息的存储,本地数据库第三 ...

  2. Codeforces Problem 598E - Chocolate Bar

    Chocolate Bar 题意: 有一个n*m(1<= n,m<=30)的矩形巧克力,每次能横向或者是纵向切,且每次切的花费为所切边长的平方,问你最后得到k个单位巧克力( k <= ...

  3. 关于路由、AP、交换机的小总结

    整理自关于路由.AP.交换机的小总结 要将各种设备连成网络,一般运用网络中的两层,即第二层的数据链路层和第三层的网络层.而设备之间需要通信就需要各自的网络地址. 第二层设备有物理地址即MAC地址,这对 ...

  4. Class类文件结构、类加载机制以及字节码执行

    一.Class类文件结构 Class类文件严格按照顺序紧凑的排列,由无符号数和表构成,表是由多个无符号数或其他数据项构成的符合数据结构. Class类文件格式按如下顺序排列:   类型 名称 数量 u ...

  5. [wikioi]传纸条

    http://wikioi.com/problem/1169/ 棋盘型的动态规划,这道题可以看成是从左上角向右下角走两条不重合的路(除了开始和结尾).动态规划要想的是状态和阶段,状态是(x1,y1,x ...

  6. 调试技巧 —— 如何利用windbg + dump + map分析程序异常

    调试技巧 —— 如何利用windbg + dump + map分析程序异常 逗比汪星人2011-09-04上传   调试技巧 —— 如何利用windbg + dump + map分析程序异常 http ...

  7. 值得推荐的C/C++框架和库 very good

    [本文系外部转贴,原文地址:http://coolshell.info/c/c++/2014/12/13/c-open-project.htm]留作存档 下次造轮子前先看看现有的轮子吧 值得学习的C语 ...

  8. Android Service 详解

    一个Service也是一种应用程序组件,它运行在后台以提供某种服务,通常不具有可见的用户界面.其它的应用程序组件可以启动一个 Service,即使在用户切换到另外一个应用程序后,这个Service还是 ...

  9. android studio 偶记

    修改项目名称 如果仅仅改了文件夹的名字,则会出现引用问题,相应的如下文件都要做相应的修改: 1. package name 要做相应调整 2. settings.gradle ,中要修改相应的moda ...

  10. decode_json 必须是unicode形式的字符

    centos6.5:/root/test#cat a1.pl use JSON qw/encode_json decode_json/; use Encode; my $data = [ { 'nam ...