Effective C++ 3e----new & delete(八)条款49:了解new-handler的行为

本文探讨C++中的new_handler机制,详细解释了当内存分配失败时,set_new_handler的作用以及new操作符如何与之交互,旨在帮助读者理解C++内存管理的高级特性。
摘要由CSDN通过智能技术生成

当我看到C++ Primer 第五版中介绍new和operator操作符的时候我非常惊叹C++的强大功能,于是趁热打铁读了More Effective C++中关于new和delete操作的有关章节,本以为自己对new和delete操作符及其内存机制已然了解的足够深入,但当我读到《STL源码剖析》的时候,又一次傻眼了,什么叫new_handler,set_new_handler又有什么作用,当内存分配失败时到底发生了什么?再一次,被C++强大的功能给震撼了!!!于是怀着对知识的渴望,打开了Effective C++ 3e来阅读有关new和delete的有关章节!

条款49, 50, 51, 52。


本章来源《Effective C++》3e


概述:




条款49:了解new-handler的行为




测试函数
#include<iostream>
#include<new>

void OutOfMemory()
{
	std::cerr << "unable to satisfy request for memory\n";
	std::abort();
}

int main()
{
	std::set_new_handler(OutOfMemory);
	while (true)
	{
		int *pBigDataArray = new int[100000000L];
	}

	return 0;
}

运行结果:

#include<iostream>
#include<new>

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 currentHander;		//new_handler只是一个函数指针,typedef void (*new_handler)()
};

//static成员必须在class定义时之外被定义(除非它们是const而且是整数型,见条款2),所以需要这么写:

std::new_handler Widget::currentHander = 0;	//在class实现文件内初始化为null


//Widget内的set_new_handler函数会将它获得的指针存储起来,然后返回先前(在调用之前)存储的指针,这也正是标准版set_new_handler的作为
std::new_handler Widget::set_new_handler(std::new_handler p) throw()
{
	std::new_handler oldHandler = currentHander;
	currentHander = p;
	return oldHandler;
}


#include<iostream>
#include<new>

class NewHandlerHolder{
public:
	explicit NewHandlerHolder(std::new_handler nh) :handler(nh){}	//取得目前的new_handler
	~NewHandlerHolder(){ std::set_new_handler(handler); }			//释放它,回复原本的global-new-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 currentHander;		//new_handler只是一个函数指针,typedef void (*new_handler)()
};

//static成员必须在class定义时之外被定义(除非它们是const而且是整数型,见条款2),所以需要这么写:

std::new_handler Widget::currentHander = 0;	//在class实现文件内初始化为null


//Widget内的set_new_handler函数会将它获得的指针存储起来,然后返回先前(在调用之前)存储的指针,这也正是标准版set_new_handler的作为
std::new_handler Widget::set_new_handler(std::new_handler p) throw()
{
	std::new_handler oldHandler = currentHander;
	currentHander = p;
	return oldHandler;
}

void *Widget::operator new(std::size_t size) throw(std::bad_alloc)
{
	NewHandlerHolder h(std::set_new_handler(currentHander));		//安装Widget的new_handler分配内存或者抛出异常
	return ::operator new(size);			//回复global new_handler,如果失败,首先恢复原本的global-new-handler,再传播异常,成功的话返回一个指针
}

Widget的客户应该类似这样使用new-handling:
void outOfMem();//函数声明,此函数在Widget对象分配失败时被调用

Widget::set_new_handler(outOfMem);//设定outOfMem为Widget的new-handling函数

Widget *pw1 = new Widget;//如果内存分配失败,调用outOfMem

std::string *ps = new std::string;//如果内存分配失败,调用global new-handling函数(如果有的话)

Widget::set_new_handler(0);//设定Widget专属的new-handling函数为null

Widget *pw2 = new Widget;//如果内存分配失败,立刻抛出异常(class Widget并没有专属的new-hangling函数)


#include<iostream>
#include<new>

class NewHandlerHolder{
public:
	explicit NewHandlerHolder(std::new_handler nh) :handler(nh){}	//取得目前的new_handler
	~NewHandlerHolder(){ std::set_new_handler(handler); }			//释放它,回复原本的global-new-handler

private:
	std::new_handler handler;
	NewHandlerHolder(const NewHandlerHolder&);						//阻止copying
	NewHandlerHolder &operator=(const NewHandlerHolder &);
};

template<typename T>		//“mixin”风格的base class,用以支持class专属的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);
	//其他的operator new版本----见条款52

private:
	static std::new_handler currentHandler;
};

//将每一个currentHandler初始化为null
template<typename T>
std::new_handler NewHandlerSupport<T>::currentHandler = 0;

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);
}






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值