栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

EffectiveC++-条款13:以对象管理资源

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

EffectiveC++-条款13:以对象管理资源

一. 内容
  1. 常见的资源有内存,文件描述器,互斥锁,图形字体和笔刷,数据库连接,网络等等。不论哪一种资源,一旦用了它,将来必须还给系统,否则会产生资源泄漏问题。
  2. 尝试在任何情况下都确保正确的资源申请和释放是困难的,考虑到函数的多重返回路径,复杂的break,continue,goto等控制语句,或者程序维护员改动软件却未充分理解随之带来的冲击。
  3. 一个较好的解决方案是:基于对象进行资源管理,我们可以借助对象的生命周期,使用构造函数,析构函数,拷贝函数进行直接易懂的资源管理。
  4. 我们可以将资源放进对象中,当函数执行完毕,该对象会自动调用析构函数,释放那些资源。
  5. C++标准库中已经存在这样的对象,名为智能指针,但它其实是个像指针一样的对象,其析构函数自动对其所指对象调用delete。
    下面演示了如何使用auto_ptr避免资源泄漏的可能
    class Resource {
    public:
        Resource(int mData): Data(mData) {}
    public:
        int Data;
    };
    
    inline Resource* GetResource() {
        return new Resource(1);
    }
    
    inline void UseResource() {
    	//调用资源调度函数并使用auto_ptr智能指针进行管理
        const std::auto_ptr ResourcePointer(GetResource());
        //常规使用资源
        std::cout << ResourcePointer->Data<<"n";
        //块语句结束时,auto_ptr对象自动调用析构函数删除所指资源。
    }
    
  6. 这个例子展示了两个关键想法:
    • 获得资源后立刻放入管理对象。以上返回的资源被当作auto_ptr的初值,实际上这种做法常被称为:资源取得的时机便是初始化的时机,简称RAII,Resource Acquisition Is Initialization,当然也存在赋值的情况。
    • 管理对象运用析构函数确保资源被释放。无论函数以何种形式完成执行,对象在离开作用域后总是会被自动销毁,保证了资源的释放。条款8保证了异常不会脱离析构函数,我们不用担心异常的问题。
  7. 但是请注意智能指针的使用,当多个auto_ptr指向同一个对象,多个auto_ptr的销毁会导致对象被delete多次,导致未定义行为。
  8. auto_ptr一个性质是通过拷贝函数赋值或构造会转移资源所有权,原先auto_ptr指针资源变为null。
        std::auto_ptr ResourcePointerOne(GetResource());
        std::cout << ResourcePointerOne->Data << "n";
        std::auto_ptr ResourcePointerTwo = ResourcePointerOne;
        //ResourcePointerOne is nullptr
        std::cout << (ResourcePointerOne.get() == nullptr ? "nullptr" : "not nullptr") << "n";
        //ResourcePointerTwo is not nullptr
        std::cout << (ResourcePointerTwo.get() == nullptr ? "nullptr" : "not nullptr") << "n";
    
  9. auto_ptr的替代方案是引用计数型智能指针,Reference-counting smart pointer(RCSP),RCSP会持续追踪共有多少对象指向某笔资源,并在无人指向它们的时候将其删除,并且可以多个智能指针指向同一资源,复制行为一如预期。但遗憾的是存在环形引用的情况,当两笔资源互指时,即使没人再使用它们,它们的引用数也不为0,导致资源泄漏。之后的weak_ptr解决了这个问题。
  10. 当然本条款重在强调对象管理资源的重要性,不在于智能指针的学习和使用,实际上现在auto_ptr已经被unique_ptr所替代。
  11. C++并没有针对动态分配的数组设计相应的智能指针,因为vector,string几乎总是可以替换其行为,如果坚持,看看Boost。
  12. 最后批注,上述演示GetResource()函数返回了未加工的指针,这简直是对资源泄漏的死亡邀约,因为调用者极易在这个指针上忘记调用delete,我们将在条款18进行修改此接口。
二. 总结
  1. 为防止资源泄漏,请使用RAII对象,它们在构造函数中获得资源并在析构函数中释放资源。
  2. 两个常被使用的RAII classes分别是tr1::shared_ptr和auto_ptr。前者通常是较佳的选择,因为其copy行为比较直观。若选择auto_ptr,复制动作会使它(被复制物)指向null。
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1011921.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号