C++不支持类专属的new-handler,类需要自定义operator new和set_new_handler静态成员函数来使用其专属的new-handler。
throwing (1)void* operator new (std::size_t size) throw (std::bad_alloc);
nothrow (2) void* operator new (std::size_t size, const std::nothrow_t& nothrow_value) throw();
placement (3) void* operator new (std::size_t size, void* ptr) throw();
一、分类:
1)void *operator new(std::size_t) throw(std::bad_alloc);
-------- 失败时,先执行std::new_handler,如果还是失败,则抛出异常。
-------- 返回值不会为空!判断指针是否为空是不正确的。
2)void *operator new(std::size_t, void*) throw();
-------- 这是通用的placement new;void *可以被替换。
-------- 必须定义一个带有同样参数的operator delete,否则执行delete时,不会有任何动作;
3)void *operator new(std::size_t, const std::nothrow_t&) throw();---基本无用
------- 不抛出异常;可以判断返回值是否为空。
------- 使用方式如 new (std::nothrow) classname;
------- 只保证operator new不抛异常,但无法保证申请成功后的"构造函数"不抛异常;所以无用。
1) new (std::nothrow) xxx; --- 相当于是std::nothrow_t x; operator new (sizeof(int), x);
2) 使用placement new;--- 它是先申请内存,再调用new (pointer) x;
3) 定义template<class t> class newhandlersupport; 在其中定义operator new和set_new_handler。
class x: public newhandlersupport<x>;
4) 在x中定义operator new。采用如x *px1 = new (specialerrorhandler) x; 方式。
class x {
public:
void f();
static void * operator new(size_t size, new_handler p); // 重载了new操作符,new-hander为new的出错处理)函数
static void * operator new(size_t size)
{ return ::operator new(size); }
};
二、为什么替换new,delete?替换时需要注意遵循哪些规则?是否有开源内存管理器?
1、理由:
检测错误;
收集统计信息;
提高速度;
节约内存;(泛用型内存管理器往往使用更多内存)
为了拟补缺省分配器中的非最佳齐位(如,double在8字节对齐情况下性能好)
为了将对象成簇集中
非传统行为
2、规则
支持分配0字节内存,转化为分配1字节内存;
循环执行分配,直到以下情况:成功?抛出异常? 其中循环执行new-handling函数。
还需要考虑operator new被子类继承的情况,是否影响子类执行。
operator new[]更复杂,还需要如何考虑存放数组元素的个数。
删除null指针永远安全。
normal new,placement new,nothrow new必须都定义。
3、
如boost程序库的Pool就是,它对于最常见的“分配大量小型对象”很有帮助。
ACE中也有各类内存分配,如内存池ACE_Cached_Allocator
三、补充:
C++11版本,new数组失败会得到如下异常bad_array_new_length,继承自std::bad_alloc。