c++中new和delete的那些事2

来源:互联网 发布:windows系统优化软件 编辑:程序博客网 时间:2024/05/29 02:49

前面已经说过operator new是用来分配未构造内存,那么其分配过程如何呢?在Effective C++中,Scott Meyers老爷子提供了一份伪码,如下:


void* operator new(std::size_t size) throw(std::bad_alloc){    using namespace std;    if(size==0)    {       size=1;    }    while(true)    {       尝试分配size bytes;       if(分配成功)       return (一个指针,指向分配得来的内存);                  new_handler globalHandler = set_new_handler(0);       set_new_handler(globalHandler);        if(globalHandler) (*globalHandler)();        else throw std::bad_alloc();    }}

函数参数列表的后面的throwstd::bad_alloc)是异常规格说明,表示本函数只允许抛出bad_alloc异常(VCVS会简单忽略此语句,即并不支持异常规格说明)。

我们知道,并没有任何不占用空间的对象。即便是一个类是空类,从此类中实例化出来的对象也要至少占用一个字节的空间,因此函数中,若碰到需要分配的内存大小size0(莫要认为此事不存在,一个可能的场景是new一个对象出来,而此对象所属的类中不含任何成员变量),便把size赋为1,再分配空间。另外,我们注意到,operator new返回的是void*指针,这一点同malloc是一样的(其实也只能返回void*,因operator new要给大大小小不同的对象分配空间,自然无法知道所有这些对象的类型,因此只能返回void*,再交由new来进行强制类型转换成特定的类型)。

此份伪码中,可能产生疑惑的当时如下语句:

new_handler globalHandler = set_new_handler(0);

set_new_handler(globalHandler);
这个new_handler是神马东西呢,set_new_handler又是神马玩意?
new_handler是一个如下类型的函数指针:
typedef void (*new_handler) ();//一个没有任何参数,并且返回值也为空的函数

set_new_handler是一个如下形式的函数:

new_handler set_new_handler(new_handler p) throw();

new_handler是一个错误处理函数,而set_new_handler正是那个决定当出现内存分配不足等错误时调用哪一个错误处理函数的函数。set_new_handler的参数和返回值都是new_handler类型,它是把参数的new_handler设置为新的错误处理函数,并返回旧的错误处理函数。set_new_handler的一份可能实现如下:

new_handler set_new_handler(new_handler p) throw(){    new_handler old_handler=current_handler;    current_handler=p;    return  old_handler;}

我们还要注意到,set_new_handler并不允许抛出任何异常(参数列表后面的throw())。
有关重新设置错误处理函数的例子如下:

class NoMem{    public:          NoMem(){}};void my_new_handler(){    throw NoMem();}new_handler Old_Handler=set_new_handler(my_new_handler);//我们把旧的错误处理函数保存下来,以待后面恢复错误处理函数为这个

operator new的伪码中,因为我们并没有任何办法可以直接获得new_handler函数指针,因此我们只有将new_handler设置为null之后又恢复原样。设计拙略却有效。


另外一个需要注意的点是whiletrue)循环,也就是说如果我们没有成功分配所需的内存,错误处理函数也不是空的话就会不停的调用错误处理函数直到成功分配所需内存。其实这也正是operator new的行为,当operator new无法满足内存分配时,它会不停的调用new_handler函数,直到分配到所需的内存。


原创粉丝点击