New需要做到什么?
1、必须返回正确的值;
2、内存不足时必须调用new-handler函数;
3、必须能对付0内存的需求;
4、避免不小心覆盖默认的new。
接下来作者对new做了比较详细的解释。
系统的new操作符实际上不止一次尝试分配内存,而是不断地,每次失败后都会调用一个new-handler函数,知道new-handler函数指针是null,new才抛出异常。
C++规定即使你new的内存是0,new也会把它看成是申请1byte来处理。作者说这是为了简化语言其他部分,但是我没有体会到是怎么简化的。不过,0实际上代表不分配,1代表至少分配一点,所以你分配1成功至少说明了你有可能分配成功,如果没可能那就直接告诉用户没法分配。
作者给出了一段new的实现伪码,其中涉及到new在尝试第一次分配内存如果失败了该如何处理的情况,显然它必须要调用某个new-handler函数,但是如何获取第一个new-handler函数呢?它是通过把set-new-handler的参数置为0来实现的。
因为new是不断尝试分配内存,所以其内部实现必然会有一个while循环,其退出条件是分配成功或者异常退出。
当你试图用父类的new去处理子类的对象分配时,你可能会遇到内存分配错误的情况,因为父类的new专为父类而生,它是根据福类对象的大小而量身定制的而不是子类。所以如果子类对象的大小是能够用父类的new来分配空间的那你就用否则你还是使用系统提供的new吧。这里不用考虑对象的大小是0的情况,因为根据C++的规定一个独立对象的大小至少是1byte。同样的道理你最好不要用父类专用的new []去套用子类,因为你不知道子类对象的大小,不过可以肯定的是子类对象要比父类对象大,所以你在父类设计之初无法知道父类的new[]分配的连续内存能放下几个子类对象,此外因为动态分配需要额外的空间来存储元素个数,所以new[]需要更多的空间。
接下来作者谈了一下有关delete的细节。对于delete你只需要保证delete的数量等于new的数量就好,不多删不少删就行,空指针直接返回。还有就是专属版delete删除专属版new,默认delete删除默认new。
在这里不得不提一下的是父类的析构函数之所以应该是virtual的理由之二是如果是非virtual析构函数,那么传递给delete的数量可能不正确。
我发现最近这几条原则很少是技巧性的原则很多是原则性的总结。
总结:
1、new应该包含一个无限循环,并在其中尝试分配内存,如果分配不了,它就调用new-handler。它应该能处理0byte申请。Class专属版还应该能处理比正确大小更大(错误)的申请。
2、delete遇到null指针不作任何事。Class专属版应该能处理比正确大小更大(错误)的申请。
条款51:编写new和delete时需固守常规
最后编辑于 :
©著作权归作者所有,转载或内容合作请联系作者
- 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
- 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
- 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
推荐阅读更多精彩内容
- 题目内容: class Fruit{int no;double weight;char key;public:vo...
- Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...