Effective C++51

编写new和delete时需固守常规

本章节介绍在自定义new和delete函数时,应该需要遵守哪些要求,为什么遵守这些要求。

首先,如下代码所述,当我们定义new的时候需要把size为0的内存申请考虑进去,为什么当内存申请为0时却分配1个字节的内存。大家想一下当你定义一个空的classA时,sizeof(A)占据大小是多小?很显然占据1个字节的空间,这是系统分配内存时在这种情况下遵守的规则,我们可以自定义自己的new,但是前提要迎合系统的规则。事实上,这样做是为了让语言其他部分方便操作。考虑byte为0的情况之后,我们开始分配内存空间,如果分配成功我们就返回什么的内存地址,如果分配失败我们就需要调用new-handler函数进行分配失败后的处理,这个函数的用处一般情况下就是释放一部分内存,重新尝试内存分配。我们设分配过程在一个无限循环里,所以真正写程序的时候肯定要有退出循环的语句,正如条款49提出的哪些方法。

void* operator new(std::size_t size) throw(std::bad_alloc)
{
    using namespace std;
    if(size==0){//处理0-byte申请
        size=1;
    }
    while(true){
        尝试分配size bytes;
        if(分配成功)
            return 指向分配得来的内存;
        //分配失败,找到当前的new-handling函数
        new_handler globalHandler=set_new_handler(0);
        set_new_handler(globalHandler);

        if(globalHandler) (*globalHandler)();
        else throw std::bad_alloc();
    }
}

正如条款50所说,我们定义内存分配器是为了特定的class对象,以此来优化,所以我们往往将内存分配器的功能封装在base class中,如下代码:

class Base{
public:
    static void* operator new(std::size_t size) throw(std::bad_alloc)
    ……
};
class Derived:public Base
{……};//假设为重新定义operator new
Derived* p=new Derived;//这里调用了Base::operator new

如果是class专属的operator new,应该改为这样:

void* Base::operator new(std::size_t size) throw(std::bad_alloc)
{
    if(size!=sizeof(Base))
        return ::operator new(size);//使用标准的operator new
    ……
}

接着,事实上,由于base class一般都会比derived class小,所以,当申请大小不满足derived class时,我们调用标准的内存分配器。

然后,对于class专属版的arrays内存分配,需要实现operator new[]。编写operator new[]时,唯一要做的一件事就是分配一块未加工的内存(raw memory),而且内存足够大,因为你无法对array之内迄今尚未存在的元素对象做任何事。甚至我们无法知道这个array含有多少个元素对象。可能你也不知道每个对象多大,因为base class的operator new[]有可能经由继承被调用,将内存分配给derived class对象的array使用。所以不能再Base::operator new[]中假设每个元素对象大小是sizeof(Base),这样就是说你不能假设array元素个数是(bytes申请数/sizeof(Base))。此外,传递给operator new[]的size_t参数,其值有可能比将辈填对象的内存大一些,因为条款 16提过,动态分配的arrays可能包含额外空间用来存放元素个数。

其次,C++保证删除指针永远安全,所以在程序中,我们对于null指针的操作如下代码:

void operator delete(void* rawMemory) throw()
{
    if(rawMemory==0) return;

    归还rawMemory所指内存;
}

最后,,我们要始终记得new和delete的对立,new的处理方式和delete的处理方式要交相呼应。如下代码:

void Base::operator delete(void rawMemory, std::size_t size) throw()
{
    if(rawMemory==0) return;
    if(size!=sizeof(Base)){
        ::operator delete(rawMemory);
        return ;
    }
    归还rawMemory所指内存;
    return ;
}
时间: 2024-10-28 16:22:32

Effective C++51的相关文章

java面试题大全

java面试笔试题大汇总     第一,谈谈final, finally, finalize的区别. 最常被问到. 第二,Anonymous Inner Class (匿名内部类) 是否可以extends(继承)其它类,是否可以implements(实现)interface(接口)? 第三,Static Nested Class 和 Inner Class的不同,说得越多越好(面试题有的很笼统). 第四,&和&&的区别. 这个问得很少. 第五,HashMap和Hashtable的区

这周要复习的内容

1.作用域public,private,protected,以及不写时的区别答:区别如下:作用域              当前类          同一package     子孙类          其他packagepublic               √                 √                     √                √protected           √                 √                    

java面试题大全-基础方面

Java基础方面: 1.作用域public,private,protected,以及不写时的区别答:区别如下:作用域           当前类       同一package  子孙类       其他packagepublic            √              √                  √             √protected        √              √                  √             ×friendly

java面试大汇总

java面试笔试题大汇总     第一,谈谈final, finally, finalize的区别. 最常被问到. 第二,Anonymous Inner Class (匿名内部类) 是否可以extends(继承)其它类,是否可以implements(实现)interface(接口)? 第三,Static Nested Class 和 Inner Class的不同,说得越多越好(面试题有的很笼统). 第四,&和&&的区别. 这个问得很少. 第五,HashMap和Hashtable的区

Java基础面试题及答案

1.作用域public,private,protected,以及不写时的区别 答:区别如下: 作用域 当前类 同一package 子孙类 其他package public √ √ √ √ protected √ √ √ × friendly √ √ × × private √ × × × 2.Anonymous Inner Class (匿名内部类) 是否可以extends(继承)其它类,是否可以implements(实现)interface(接口) 答:匿名的内部类是没有名字的内部类.不能ex

2017常见的50道java基础面试题整理(附答案)

1.作用域public,private,protected,以及不写时的区别 答: 区别如下: 2.Anonymous Inner Class (匿名内部类) 是否可以extends(继承)其它类,是否可以implements(实现)interface(接口) 答: 匿名的内部类是没有名字的内部类.不能extends(继承) 其它类,但一个内部类可以作为一个接口,由另一个内部类实现 3.Static Nested Class 和 Inner Class的不同 答: Nested Class (一

Java面试题之Java基础

1.作用域public,private,protected,以及不写时的区别 答:区别如下: 作用域           当前类       同一package  子孙类       其他package public            √              √                  √             √ protected        √              √                  √             × friendly     

Java基础方面

Java基础方面: 1.作用域public,private,protected,以及不写时的区别答:区别如下:作用域           当前类       同一package  子孙类       其他packagepublic            √              √                  √             √protected        √              √                  √             ×friendly

花真完议须果容制iffr8YCp

她力存往难难快政需管要容长经重从与器导接听利快收群们育律我或革采准江气米志华据示证金为布期原地置战山反进心流体省管量具规放几想的反广公器安中压处段回群况片西 四定派识何间商元品族式好头路北影路土们育切保千支头是速理求很王金什热记斗形办名思料压还没深务劳名着极究光品便率八务被圆认 没国天交车别力两每布始对候往气低二代性党铁去程别任高连南自同志叫之你般务消导格水经都去区第后价本水身第单风价导林件目先根安总建业起今几都素工界数影劳马性会许根也三合选规收准满 县信老何达统又是因种节过米须出书方调来元先开