條款49:瞭解new-handler的行爲

/*條款49:瞭解new-handler的行爲*/
#include<iostream>
using namespace std;
//operator new 當無法滿足某一內在分配需求時,它會拋出異常,返回NULL指針,某些舊式編譯器目前也還那麼做,也可以當operator拋出異常之前先調用一個·客戶指定錯誤處理函數(new-handler),但客戶必須調用set_new_handler,那是聲明於<new>的標準程序庫函數
namespace std{
	typedef void (*new_handler)();
	new_handler set_new_handler(new_handler p)thorw();//當operator new 無法分配足夠內在時,set_new_handler則是獲得一個new_handler並返回 一個new_handler
}
//這是operator new 無法分配足夠內在時set_new_handler,調用的函數
void outOfMem(){
	std::cerr<<"Unable to satisfy request for memory\n";
	std::abort();
}//主函數進行調用 
//一個設計良好的new-handler函數必須做以下事情:
//1 讓更多內在可被使用 2 安裝另一個new-handler 3 卸除new-handler 也就是讓NULL傳給set_new_handler 4 拋出bad_alloc(或派生自bad_alloc)的異常 5 不返回 通常是調用abort或exit
class X{
public:
	static void outOfMemory();
	//..
};
class Y{
public:
	static void outOfMemory();
	//..
};
// C++ 並不支持class 專屬的new-handlers ,w你可以自己實現出這種行爲 ,只需令第一個class提供自己的set_new_handler和operator new 即可
template<typename T> // "minxin"風格的基類 用以支持類專屬的set_new_handler
class NewHandlerSupport{
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;
}
template<typename T>
std::new_handler
NewHandlerSupport<T>::set_new_handler(std::new_handler p)throw(){
	std::new_handler oldHandler = currentHandler;
	currentHandler = p;
	return oldHandler;
}
template<typename T>
void * NewHandlerSupport<T>::operator new(std::size_t size)throw(std::bad_alloc){
	NewHandlerHolder h(std::set_new_handler(currentHandler));
	return ::operator new(size);
}
//..
class Widget:public NewHandlerSupport<Widget>{
	//.... 
};//這樣就可以爲Widget添加set_new_handler ,
class NewHandlerHolder{
public:
	explicit NewhandlerHolder(std::new_handler nh):handler(nh){}//取得目前的new-handler
	~NewHandlerHolder(){
		std::setA_new_handler(handler);	
	}
private:
	std::new_handler handler;// 記錄下來
	NewHandlerHolder(const NewHandlerHolder&);//阻止copying
	NewHandlerHolder&operator=(const NewHandlerHolder&);
}
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 currentHandler = 0;//類外定義,除非它是const型的
std::new_handler set_new_handler(std::new_handler p) throw(){
	std::new_handler oldHandler = currentHandler;
	currenthandler = p;
	return oldhandler;
}
void *Widget::operator new(std::size_t size)throw(std::bad_alloc){
	NewHandlerHolder h(std::set_new_handler(currentHandler));//安裝widget的new-hanler
	return ::operator new(size);//分配內在或拋出異常恢復 glolbe new-handler
}
int main(){
	std::set_new_handler(outOfMem);
	int *pBigDataArray = new int[100000000L];
	X*p1 = new X;//如果分配不成功調用X::outOfMemory
	Y*p2 = new Y;
	//
	void outOfMem(); //函數聲明,此函數在widget對象分配失敗時被調用
	Widget::set_new_handler(outOfMem);//設定outOfMem爲Widget的new-handling函數
	Widget*pw1 = new widget;//如果內在分配失敗,調用 outOfMem;
	std::string*ps = new std::string // 如果內在分配失敗 調用globe new-handling函數(如果有的話)
	Widget::set_new_handler(0);//設定widget專屬的new-handling函數爲NULL
	Widget*pw2 = new Widget;//如果內存分配失敗,立刻拋出異常,(class Widget並沒有專屬的new-handling 函數)	

	return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章