zoukankan      html  css  js  c++  java
  • effective C++ 条款 13:以对象管理资源

    资源是,一旦用了,将来必须还给系统,除了内存常见的还有文件描述符(file description)、互斥锁、图形界面中的笔刷、数据库连接

    以及网络socket。考虑到异常、函数内多重回传路径、程序维护员软件改动却没有理解随之而来的冲击,发现资源管理的特殊手段还不很充分够用。

    假设一个各式各样的投资类型继承的一个root class Investment:

    class Investment {...};

    假设通过一个工厂函数供应我们某特定的Investment对象:

    Investment* createInvestment();//返回指向Investment继承体系的动态分配对象。调用者有责任删除它。

    void f()
    {
        Investment* pInv = createInvestment();  //调用factory函数
        ...
        delete pInv;   //释放pInv所指对象
    }

    若果…中有一个过早的return语句,或者抛出异常,那么控制流将不会幸临delete。

    为确保资源总是被释放,我们需要将资源放进对象内,这样便可依赖c++的“析构函数自动调用机制”确保资源被释放。标准程序库提供的auto_ptr正是针对这种形势设计的特制产品。auto_ptr是一个“类指针(pointer-like)对象”:

    void f()
    {
        std::auto_ptr<Investment> pInv(createInvestment());
        ...
    }  //经由auto_ptr的析构函数自动删除pInv

    1.获得资源后立即放进管理对象(managing object)内。createInvestment返回的资源被当做其管理者auto_ptr的初值。

    “以对象管理资源”的观念常被称为“资源取得时便是初始化时”(resource Acquisition is Initialization;RAII),有时获得的资源拿来赋值(而非初始化)某个管理对象,但不论哪种做法,每笔资源在获得的同时立刻被放进管理对象中。

    2.管理对象运用析构函数确保资源被释放。一旦对象被销毁(当对象离开作用域),其析构函数自然会自动调用,于是资源被释放。

    由于autu_ptr被销毁时会自动删除它所指之物,所以一定不要让多个auto_ptr同时指向同一个对象。为防止这个问题,auto_ptr有一个不寻常的性质:若通过copy构造函数或copy assignment操作符复制它们,它们会变成null,而复制所得的指针取得资源的唯一使用权。

    std::auto_ptr<Investment> pInv1(createInvestment());
    std::auto_ptr<Investment> pInv2(pInv1);//现在pInv2指向对象,pInv1被设为null
    pInv1 = pInv2;//现在pInv1指向对象,pInv2被设为null

    这个诡异的复制行为,使得要求其元素发挥“正常的”复制行为的像stl容器这种容不得auto_ptr。

    auto_ptr的替代方案是“引用计数型智慧指针”(reference-counting smart pointer;RCSP)PCSP持续追踪共有多少对象指向

    某笔资源,并在无人指向它时删除该资源。类似于垃圾回收,但无法打破环状引用(cycle of reference,例如两个其实已经没有被使用的对象彼此互指,因而好像在“被使用”状态)。

    TR1的tr1:shared_ptr就是个RCSP,所以可以这么写f:

    void f()
    {
        std::tr1::shared_ptr<Investment> pInv(createInvestment());
        ...
    }//经由shared_ptr的析构函数自动删除pInv

    shared_ptr的复制正常多了

    void f()
    {
        std::tr1::shared_ptr<Investment> pInv1(createInvestment());
        std::tr1::shared_ptr<Investment> pInv2(pInv1);//pInv1和pInv2指向同一个对象
        pInv1 = pInv2;
        ...
    }//pInv1和pInv2被销毁,他们指向的对象也就被销毁。

    所以shared_ptr可以被用于stl容器及其他“auto_ptr之非正统复制行为并不合适”的语境上。

    auto_ptr及shared_ptr在其析构函数内做delete而不是delete[]动作。那意味着在动态分配而得的array身上使用auto_ptr或shared_ptr是个馊主意。因为vector和string几乎总是可以替代动态分配而得的数组。boost::scope_array 和boost::shared_array classes是针对数组设计的类似auto_ptr和tr1::shared_ptr那样的类。

    防止资源泄漏,请使用RAII对象,他们在构造函数中获得资源并在析构函数中释放资源。shared_ptr比auto_ptr是个较佳的选择

    因为其copy行为比较直观。

  • 相关阅读:
    git删除目录,且保留本地的
    gitpush 免密码
    git常用操作
    ubuntu安装Nodejs
    ubuntu如何配置samba
    用AI将png转成svg做字符图标教程
    windows server 2012设置远程连接断开后自动注销
    windows 2012执行计划任务错误:操作员或系统管理员拒绝了请求(0x800710E0)
    删除节点
    代理 XP”组件已作为此服务器安全配置的一部分被关闭。系统管理员可以使用 sp_configure 来启用“代理 XP”。
  • 原文地址:https://www.cnblogs.com/lidan/p/2322267.html
Copyright © 2011-2022 走看看