《Effective C++第三版》读书笔记——定制new和delete

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专属版本则还需要处理"比正确大小更大的错误申请"
 

 
 
  1. //non-member operator new伪代码 
  2.   void* operator new(std::size_t size)throw(std::bad_alloc) 
  3.   { 
  4.       using namespace std; 
  5.       if(size == 0){ 
  6.           size = 1;    //处理0-bye申请,将它视为1-bye申请,因为C++不允许大小为0的对象 
  7.       } 
  8.       while(true){ 
  9.           尝试分配size bytes; 
  10.           if(分配成功){return 指向内存的指针;} 
  11.           //分配失败,找出目前的new-hander函数并调用 
  12.           new_handler globalHandler = set_new_handler(NULL); 
  13.           set_new_handler(globalHandler); 
  14.           if(globalHandler){ 
  15.               (*globalHandler)(); 
  16.           }else
  17.               throw std::bad_alloc(); 
  18.           } 
  19.       } 
  20.   } 



   2. operator new[]唯一需要做的一件事就是分配一块未加工内存.
   3. operator delete应该在收到null指针时,不做任何事.class专属版本则还应该处理"比正确大小更大的错误申请"

8.3 写了placement new也要写placement delete
============================================
   1. 如果operator new接受的参数除了一定会有的那个size_t之外,还有其他参数,这便是个所谓的placement new.
   2. 相应的placement delete指"参数个数和类型都与operator new相同的"operator delete
   3. 运行期,若replacement new抛出异常,则系统会去找与placement new相对应的placement delete版本,若找不到则什么也不做.
      但是placement delete只有在"伴随placement new调用而触发的构造函数"出现异常时才会被编译器自动调用.对一个指针显式调用delete不会导致调用placement delete.
   4. 缺省情况下,C++在global作用域提供三种形式的operatornew
     

 
 
  1. void* operator new(std::size_t)throw(std::bad_alloc);  //normal new 
  2. void* operator new(std::size_t,void*) throw();         //placement new 
  3. void* operator new(std::size_t,const std::nothrow_t&)throw()//nothrow new 


   5. 当声明了专有类的new和delete之后,请注意,它会遮掩std的标准new和delete.

本文出自 “暗日” 博客,请务必保留此出处http://darksun.blog.51cto.com/3874064/1148742

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值