实现类的特定的set_new_handler,operator new ,operator delete

首先让我们了解下new-handler的行为:在opeartor new抛出异常以反应一个未获满足的内存需求之前,它会先调用一个客户指定的错误处理函数,一个所谓的new-handler。(这其实并非全部事实,operator new真正做的事情稍微更复杂些,详见条款51。)为了指定这个“用以处理内存不足的函数”,客户必须调用set_new_handler,那是声明<new>的一个标准程序库函数:

namespace std
{

typedef void(*new_handler)();

new_handler set_new_handler(new_handler p)throw();
}

      如你所见,new_handler是个typdef,定义出一个函数指针类型,所指向的函数是没有参数也不返回任何东西。set_new_handler则是“获得一个new_handler并返回一个new_handler”的函数。set_new_handler的参数是一个指针,指向operator new 无法分配足够内存时该被调用的函数,其返回值也是个指针,指向调用set_new_handler时要被替换的那个new-handler函数。

 

当operator new无法满足内存申请时,它会不断调用new-handler函数,直到找到足够内存。引起反复调用的代码显示于条款51,这里的高级描述已足够获得一个结论,那就是一个设计良好的new-handler函数必须做的事情:
1.让更多内存可被调用。 这便造成operator new 内的下一次内存分配动作可能成功。实现此策略的一个做法是,程序一开始执行就分配一大块内存,而后当new-handler第一次被调用,将它们释还给程序使用。

2.安装另一个new-handler。如果目前这个new-handler无法取得更多可用内存,或许它知道另外哪个new-handler有此能力。果真如此,目前这个new-handler就可以安装另外那个new-handler以替换自己(只要调用set_new_handler)。下次当operator new调用new-handler,调用的将是最新安装的那个

3.卸载new-handler。也就是将null指针传给set_new_handler。一旦没有安装任何new-handler,operator new 会在内存分配不成功时抛出异常。

4.抛出bad_alloc(或派生字bad_alloc)的异常。这样的异常不会被operator new 捕捉,因此会被传播给内存索求处。

5.不返回。通常调用abort或exit.

这些选择让你在实现new-handler函数时拥有很大弹性。

 

好,知道这些后我们就开始简单地实现类的特定的set_new_handler,operator new ,operator delete

见代码:
#include <iostream>
using namespace std;
class NewHandlerHolder   //用于恢复原来的new-handler,思想采用RAII机制
{
public:
	explicit NewHandlerHolder(new_handler h);
	~NewHandlerHolder();
private:
	new_handler m_handler;
	NewHandlerHolder(const NewHandlerHolder& rhs);
	new_handler& operator=(const NewHandlerHolder& rhs);
};
NewHandlerHolder::NewHandlerHolder(new_handler h)
{
	m_handler=h;
}
NewHandlerHolder::~NewHandlerHolder()
{
	set_new_handler(m_handler);
}

//建立一个"mixin"风格的base class,这种base class用来允许derrived classes继承特定的功能(特定的set_new_handler,operator new ,operator delete)
template<class T>
class NewHandlerSupport {
public:
	static new_handler set_new_handler(new_handler p) throw();
	static void* operator new(size_t size) throw(bad_alloc);
	static void operator delete (void* pMem,size_t size);
protected:
	static new_handler m_CurrentHandler;
};
template<class T>
new_handler NewHandlerSupport<T>::m_CurrentHandler=0;

template<class T>
new_handler NewHandlerSupport<T>::set_new_handler(new_handler p) throw()
{
	new_handler oldHandler=m_CurrentHandler;
	m_CurrentHandler=p;
	return oldHandler;
}
template<class T>
void* NewHandlerSupport<T>::operator new(size_t size) throw(bad_alloc)
{
	NewHandlerHolder(::set_new_handler(m_CurrentHandler));
	return ::operator new(size);
}
template<class T>
void NewHandlerSupport<T>::operator delete(void* pMem,size_t size)
{
	return ::operator delete(pMem);
}
class widget:public NewHandlerSupport<widget>
{
public:
protected:
private:
};
void OutMemory()
{
	cerr<<"unable to satisfy request for memory"<<endl;
	abort();
}
int main()
{
	widget::set_new_handler(OutMemory);
	widget* p=new widget;
	delete p;
	p=NULL;
	return 0;
}


你可能感兴趣的:(实现类的特定的set_new_handler,operator new ,operator delete)