8 定制new和delete
~~~~~~~~~~~~~~~~~~ 8.1 了解new-handler的行为 ========================== 1. 当opeartor new无法满足某一内存分配需求时,它会抛出异常.在这之前,它会先调用一个客户指定的错误处理函数,所谓的new-handler 2. 用户必须通过调用set_new_handler来设置new-handler函数,set_new_handler的参数是指向new-handler函数的指针 3. new-handler函数应该没有参数,也不返回任何东西(void) 4. 当operator new无法满足内存申请时,它会 *不断* 调用new-handler函数,直到找到足够内存! 5. 一个设计良好的new-handler函数必须做以下事情中的一个或几个 * 让更多内存可被使用 一个做法是,程序一开始执行就分配一大块内存,然后当new-handler第一次调用,将它们释放给程序使用 * 安装另一个new-handler (否则会不断调用这个new-handler,进入死循环) * 卸除new-handler 也就是将null指针传给set_new_handler,这样operator new会在内存分配不成功时抛出异常 * 抛出bad_alloc * 退出程序 通常调用abor或exit 6. 使用new (std::nothrow),如果分配内存失败,不会抛异常,而是返回NULL值,nothrow定义于<new> 8.2 写new和delete时需固守常规 ============================== 1. operator new应该内含一个无穷循环,并在其中尝试分配内存,如果无法满足内存需求,就调用new-handler. 它也应该有能力处理0bytes申请. 由于类中的operator new成员函数会被子类继承,因此class专属版本则还需要处理"比正确大小更大的错误申请"- //non-member operator new伪代码
- void* operator new(std::size_t size)throw(std::bad_alloc)
- {
- using namespace std;
- if(size == 0){
- size = 1; //处理0-bye申请,将它视为1-bye申请,因为C++不允许大小为0的对象
- }
- while(true){
- 尝试分配size bytes;
- if(分配成功){ return 指向内存的指针;}
- //分配失败,找出目前的new-hander函数并调用
- new_handler globalHandler = set_new_handler(NULL);
- set_new_handler(globalHandler);
- if(globalHandler){
- (*globalHandler)();
- }else{
- throw std::bad_alloc();
- }
- }
- }
- * void* operator new(std::size_t)throw(std::bad_alloc); //normal new
- * void* operator new(std::size_t,void*) throw(); //placement new
- * void* operator new(std::size_t,const std::nothrow_t&)throw()//nothrow new