Part8:定制new和delete

来源:互联网 发布:linux域控 编辑:程序博客网 时间:2024/05/02 06:12

当计算环境(例如java和.net)夸耀自己内置“垃圾回收能力”的当今,C++对内存管理的纯手工方法看起来老土。但是许多苛刻的系统程序开发人员之所以选择C++,就是因为它允许他们手工管理内存。
这样做的前提是,了解C++内存管理例程的行为。这部分的两个主角是分配例程和归还例程(allocation and deallocation routines,也就是operator new and operator delete),配角是new-handler,这是当operator new无法满足客户的内存需求时所调用的函数。
需要注意:STL容器所使用的heap内存是由容器所拥有的分配器对象管理,不是被new和delete直接管理。
set_new_handler()方法在new分配内存失败时系统自动调用该函数,没有出错不会进行调用

#include<iostream>using namespace std;void fun(){    cout<<"error occur when allocate heap"<<endl;}int _tmain(int argc, _TCHAR* argv[]){    std::new_handler p = fun;    set_new_handler(p);    long* pBigDataArray = new long[1000000000L];    getchar();    return 0;}

如果想对不同的类在分配类存是出现了错误,从而调用不同的处理函数,我们可以把函数的定义放入不同的类定义中。
比如:假设你打算处理Widget class的内存分配失败情况,首先你必须登录“当operator new无法为一个Widget对象分配足够内存时”调用的函数,所以需要声明一个类型为new_handler的static成员,用以指向class Widget的new_handler。
Widget的定义像如下:

class Widget{public:    static std::new_handler set_new_handler(std::new_handler p) throw();    static void* operator new(std::size_t size) throw(std::bad_alloc);private:    static std::new_handler currentHandler;};std::new_handler Widget::currentHandler = 0;std::new_handler Widget::set_new_handler(std::new_handler p) throw(){    std::new_handler oldHandler = currentHandler;    currentHandler = p;    return oldHandler;}

最后Widget的operator new 做如下事情。
1 调用标准set_new_hanlder,告知Widget的错误处理函数,这会将Widget的new_handler安装为global new-handler。
2 调用global operator new,执行实际之内存分配,如果分配失败,global operator new会调用Widget 的 new-hanler,因为那个函数才刚被安装为global new-handler。如果global operator new最终无法分配足够内存,会抛出一个bad_alloc异常。

  • Rule50:了解new和delete的合理替换时机
    Understand when it makes sense to replace new and delete。
    为什么有时想要替换编译器提供的operator new 或operator delete呢?
    下面是三个最常见的理由:
    1、用来检测运用上的错误
    通过在分配类存的后面追加额外空间放置特定的byte patterns,即签名,operator deletes便得以检查上述签名是否原封不动,若否就表示在分配区的某个生命时间点发生了变化。
    2、为了强化效果。
    编译器所带的operator new和operator delete主要用于一般目的,如果你对你的程序的动态内存运用形态有深刻的了解,通常可以发现,定制版的operator new和operator delete性能胜过缺省版本,他们的表现经常是快,且需要的内存比较少。
    3、为了收集使用上的统计数据。

  • Rule51:编写new和delete时需要固守常规
    adhere to convention when writing new and delete.

operator new的返回值十分单纯,如果他有能力供应客户申请的内存,就返回一个指针指向那块内存。如果没有那个能力,就使用set_new_handler,并抛出一个bad_alloc异常。
Widget *pw = new Widget;
这句语句共有两个函数被调用:一个是用以分配内存的operator new,一个是Widget的default构造函数。

0 0