• Effective C++笔记:资源管理


    资源:动态分配的内存、文件描述器、互斥锁、图形界面中的字型与笔刷、数据库连接以及网络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。

  • 相关阅读:
    VK Cup 2012 Qualification Round 1 C. Cd and pwd commands 模拟
    VK Cup 2015
    DP总结 ——QPH
    Codeforces Round #244 (Div. 2) B. Prison Transfer 线段树rmq
    Codeforces Round #311 (Div. 2) E. Ann and Half-Palindrome 字典树/半回文串
    Codeforces Round #311 (Div. 2) D. Vitaly and Cycle 图论
    Codeforces Round #311 (Div. 2) C. Arthur and Table Multiset
    Codeforces Round #311 (Div. 2)B. Pasha and Tea 水题
    Codeforces Round #311 (Div. 2) A. Ilya and Diplomas 水题
    Codeforces Round #260 (Div. 1) D. Serega and Fun 分块
  • 原文地址:https://www.cnblogs.com/ronny/p/3745098.html
Copyright © 2020-2023  润新知