• 《Effective C++》定制new和delete:条款49-条款52


    条款49:了解new-handler的行为

    • 当operator new无法分配出内存会抛出异常std::bad_alloc
    • 抛出异常前会反复调用用户自定义的new-handler函数直至成功分配内存
    // 自定义new_handler函数
    void outOfMem() {
        cerr << "Unable to satisfy request for memory" << endl;
        abort();
    }
    //测试
    int main() {
         set_new_handler(outOfMem);  //写入new_handler函数
         int* pBigDataArray = new int[100000000000000000L];
         return 0;
    }  //输出 :Unable to satisfy request for memory
    
    //声明于<new>中的标准程序函数
    namespace std {
        typedef void (*new_handler) ();
        new_handler set_new_handler(new_handler p) throw();
    }
    
    • 为不同的class写不同的new-handler函数
    #include <stdio.h>
    #include <iostream>
    #include <vector>
    using namespace std;
    
    class NewHandlerHolder {
    public:
        explicit NewHandlerHolder(new_handler nh)
            : handler(nh) {}
    
        ~NewHandlerHolder() {std::set_new_handler(handler);}
    private:
        new_handler handler;
        NewHandlerHolder(const NewHandlerHolder&) {}
        NewHandlerHolder& operator= (const NewHandlerHolder&) {}
    
    };
    
    template<typename T>
    class NewHandlerSupport {
    public:
        static new_handler set_new_handler(new_handler p) throw();
        static void* operator new[](size_t size) throw(bad_alloc);
    private:
        static new_handler currentHandler;
    };
    
    template<typename T>
    new_handler NewHandlerSupport<T>::currentHandler = 0;
    
    template<typename T>
    new_handler NewHandlerSupport<T>::set_new_handler(new_handler p) throw() {
        new_handler oldHandler = currentHandler;
        currentHandler = p;
        return oldHandler;
    }
    
    template<typename T>
    void* NewHandlerSupport<T>::operator new[](size_t size) throw(bad_alloc) {
        NewHandlerHolder h(std::set_new_handler(currentHandler));
        return ::operator new[](size);
    }
    
    
    class Widget : public NewHandlerSupport<Widget>{
    
    };
    
    void outOfMem() {
        cerr << "Unable to satisfy request for memory" << endl;
        abort();
    }
    
    int main() {
        Widget::set_new_handler(outOfMem);
        Widget* pwl = new Widget[100000000000L];
    
        return 0;
    }
    

    条款50:了解new和delete的合理替换时机

    • 有许多理由需要自定new和delete,包括改善性能、对heap运用错误进行调试、手机heap使用信息

    条款51:编写new和delete时需固守常规

    • operator new 应该包含一个无穷循环,并在其中尝试分配内存,如果无法满足内存需求,就调用new-handler函数,且要有能力处理 0 bytes申请。
    • operator delete应该在收到null指针时不做任何事情 

    条款52:写了placement new也要写placement delete

    • 当写new的表达式(Widget* pw = new Widget)时,两个函数被调用
      • 一个是用以分配内存的 operator new
      • 另一个是Widget的default构造函数
    • 如果在调用构造函数失败,编译器会寻找一个“带相同额外参数”的operator delete,找不到调用不了,会造成资源泄漏
  • 相关阅读:
    三目运算符不易发现的错误
    [转]理解C# 4 dynamic(1)
    [转]C# and the using Statement in 3 seconds and a bug in Reflector
    异步上传文件多种方式归纳
    JQuery的两个each方法的注意点
    CRM2011 concurrency问题及解决方案
    [转]Android与电脑局域网共享之:Samba Client
    [转]Android与电脑局域网共享之:Samba Server
    [转]SQL2005后的ROW_NUMBER()函数的应用
    Javascript中布尔运算符的高级应用
  • 原文地址:https://www.cnblogs.com/narjaja/p/10239359.html
Copyright © 2020-2023  润新知