您的位置:首页 > 其它

Part8:定制new和delete

2016-07-07 11:08 155 查看
当计算环境(例如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构造函数。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: