• [Effective C++ --013]以对象管理资源


    这一节基本讲述的是将资源放进管理对象,防止忘记释放资源。

    1.一般New和Delete使用场景

    void fun() {
        SimpleClass*  pSimpleClass1 = new SimpleClass;
        ....     // 如果这中间发生异常返回,则delete pSimpleClass1将不会被执行,造成内存泄漏
    
        delete pSimpleClass1;
        SimpleClass*  pSimpleClass2 = createSimpleClass();
        ....    // 如果这中间发生异常返回,则delete pSimpleClass1将不会被执行,造成内存泄漏
        delete pSimpleClass2;
    }

    即使通过严守规约使“...”没有会产生异常的代码,或者对异常的情况进行特殊处理。但是随着代码的不断维护,“...”很容易就会被加入会产生异常的代码,而delete的处理也就很容易被忽略了。
    针对这样的情况,条款13要求,以对象管理资源。

    2.如果不清楚资源将以什么方式来释放,我们可以使用自动指针auto_ptr与shared_ptr来实现:

    auto_ptr使用场景

    void funAutoPtr() {
        std::auto_ptr<SimpleClass> pSimpleClass1(new SimpleClass);
        ....
        std::auto_ptr<SimpleClass> pSimpleClass2(createSimpleClass());
        ....
    }

    shared_ptr使用场景

    void funAutoPtr_shared() {
        std::tr1::shared_ptr<SimpleClass> pSimpleClass1(new SimpleClass);
        ....
        std::tr1::shared_ptr<SimpleClass> pSimpleClass2(createSimpleClass());
        ....
    }

    两者的区别:

    auto_ptr:如通过拷贝构造函数湖泊拷贝赋值操作符赋值他们,自动指针将变成NULL,而复制所得的指针将取得指针指向的资源唯一拥有权

    shared_ptr:拷贝完后两者都指向同一资源

    auto_ptr复制行为场景

    void funAutoPtrCopy() {
        std::auto_ptr<SimpleClass> pSimpleClass1(createSimpleClass);  //pSimpleClass1指向createSimpleClass返回的实例
        std::auto_ptr<SimpleClass> pSimpleClass2(pSimpleClass1);  //现在pSimpleClass2指向实例,而pSimpleClass1被设为null
        pSimpleClass1 = pSimpleClass2;  //现在pSimpleClass1指向实例,而pSimpleClass2被设为null
    }

    shared_ptr复制行为场景

    void funAutoPtrCopy_shared() {
        std::tr1::shared_ptr<SimpleClass> pSimpleClass1(createSimpleClass);  //pSimpleClass1指向createSimpleClass返回的实例
        std::tr1::shared_ptr<SimpleClass> pSimpleClass2(pSimpleClass1);  //现在pSimpleClass1和pSimpleClass2同时指向实例
        pSimpleClass1 = pSimpleClass2;  //同上,无任何改变
    }

    3.自动指针不智能的时候

    auto_ptr针对Array使用的错误场景

    void funAutoPtrError() {
        std::auto_ptr<std::string> pStringArray(new std::string[10]);
        ....
        std::auto_ptr<int> pIntArray(new int[1024]);
        ....
    }

    shared_ptr针对Array使用的错误场景

    void funAutoPtrError_shared() {
        std::tr1::shared_ptr<std::string> pStringArray(new std::string[10]);
        ....
        std::tr1::shared_ptr<int> pIntArray(new int[1024]);
        ....
    }

    这是为什么呢?

    因为auto_ptr与shared_ptr两者在析构函数内做的都是delete而不是delete[]操作。这就意味着动态分配得到的数组是不能完全得到释放的。

    ◆总结

    1.为防止资源泄露,请使用RAII(Resourse Acquisition Is Initialization)"资源取得时机便是初始化时机"对象,它们在构造函数中获得资源并在析构函数中释放资源。

    2.两个常用的RAII class分别是shared_ptr和auto_ptr,前者通常是较佳选择,因为其copy行为比较直观。若选择auto_ptr,复制动作会使它(被复制物)指向NULL。

  • 相关阅读:
    A B
    hdu 4656 Evaluation [任意模数fft trick]
    bzoj 3451: Tyvj1953 Normal [fft 点分治 期望]
    bzoj 3509: [CodeChef] COUNTARI] [分块 生成函数]
    hdu 5730 Shell Necklace [分治fft | 多项式求逆]
    hdu 4609 3-idiots [fft 生成函数 计数]
    UVA 12633 Super Rooks on Chessboard [fft 生成函数]
    Codeforces Round #410 (Div. 2)
    形式幂级数 [学习笔记]
    Python 字符串前面加u,r,b,f的含义
  • 原文地址:https://www.cnblogs.com/hustcser/p/4103431.html
Copyright © 2020-2023  润新知