C++ New and delete
要点
set_new_handler
std::new_handler 给机会处理 new 的异常.但是是个 global 的.
下面实现的针对某个类的.
要点:
1. 重载new[];
2. 重载的new,其实还是::operator new, 不过是自定义下new_handler;
3. new完毕 恢复global new_handler;
#include <iostream>
#include <new>
#include <exception>
/** @brief NewHandlerHoder */
class NewHandlerHoder {
public:
NewHandlerHoder(const std::new_handler h): holder(h) {}
~NewHandlerHoder(){
//恢复holder里的callback
std::set_new_handler(holder);
}
//Forbid copy, =
NewHandlerHoder(const NewHandlerHoder & ) =delete;
NewHandlerHoder & operator=(const NewHandlerHoder &)=delete;
private:
std::new_handler holder;
};
/** @brief NewHander */
class NewHander {
public:
static std::new_handler set_new_handler( std::new_handler n) {
auto old = cur;
cur = n;
return old;
}
static void* operator new[](std::size_t size) {
std::cout << "my new" << std::endl;
// 如果cur设置了 设置为cur
//保存旧的global new_handler
NewHandlerHoder h(std::set_new_handler(cur));
return ::operator new(size);
//结束后通过RAII的方式恢复old global new_handler
}
private:
static std::new_handler cur;
//目的即使重写operator new?
};
//初始化
std::new_handler NewHander::cur = nullptr;
//任何继承NewHandler的类,都具备这样的能力
class A : public NewHander {
public:
private:
int m[1000];
};
void new_error()
{
std::cout << "new failed" << std::endl;
//抛自定义的异常
throw std::string("mynew_bad_alloc");
//std::exit(1);
//
}
void item49()
{
//std::set_new_handler(new_error);
try {
int * p = new int[100000000000000l];
} catch(std::string & e) {
std::cout << e << std::endl;
}
}
int main()
{
//item49();
// new handler just for A;
A::set_new_handler(new_error);
//new[] 已经重写了
try{
A* arr = new A[1000000L];
} catch (const std::string & e) {
std::cout << e << std::endl;
}
}
output:
my new
new Failed
out
上面代码还要问题,如果有 B,也继承自 NewHanlder
class B : public NewHander {
private:
int m[1000];
};
A::set_new_handler(new_error);
try{
B* arr = new B[1000000L];
} catch (const std::string & e) {
std::cout << e << std::endl;
}
通过 A 设计的 handler,对 B 也起作用了!
因为 NewHander 不是实体各异的,也就是共享了 staitc 1 个 cur;
解决之道自然是实现 template<typename T> Newhander
,即模板类,这样编译多态,不同的具体化的模板类,都有自己的 static cur.
class A : public NewHandler<A> {...}
class B : public NewHandler<B> {...}
这种继承方法确实怪异,叫curiously recurring template pattern
,CRTP.