定制new和delete
2012-12-20 13:55
423 查看
Item 49 Understand the behavior of the new-handler.了解new-handler的行为。
当operator new抛出异常之前以反映一个未满足的内存需求之前,会先调用称为new-handler的客户指定的错误处理函数。
new_handler是一个typedef的函数指针:typedef void ( *new_handler )( );
定制模板基类来定制operator new和set_new_handler函数的办法如下:
其中采用了用对象管理资源的手法。template机制为会每一个T生成一份currentHandler。
注意的一件事情:operator new不止一次尝试分配内存,并在每次失败后调用new-handling函数,只有当new-handling函数的指针是null,operator new才会抛出异常。
new-handler一般做以下几件事情:让更多内存可用,安装另一个new-handler,卸除new-handler,抛出bad_alloc异常,或是承认失败而直接return。
Item 50 Understand when it makes sense to repace new and delete.了解new和delete的合理替换时机。
一般有如下理由:
(1)用来检测运用上的错误。
(2)为了强化效能。
(3)为了收集使用上的统计数据。
(4)为了降低缺省内存管理其带来的空间额外开销。
(5)为了弥补缺省分配器中的非最佳齐位。
(6)为了将相关对象成簇集中。placement new。
(7)为了获得非传统的行为。
但无论有何种理由,请确认的确想替换掉编译器提供的operator new。
Item 51 Adhere to convention when writing new and delete.编写new和delete时需固守常规。
operator new应该内含一个无穷循环,并在其中尝试分配内存,如果它无法满足内存需求,就该调用new-handler。
operator new应该有能力处理0byte申请。class专属版本则应该处理“比正确大小更大的(错误)申请”。
//不太明白的地方。
operator delete应该在收到null指针时不做任何事。class专属版本则还应该处理“比正确大小更大的(错误)申请”。
Item 52 Write placement delete if you write placement new.写了placement new也要写placement delete。
Widget *w=new (cerr)Widget;
这样的一句代码,引起的是在Widget类内定义的static void* operator new(size_t size,ostream& os) throw(bad_alloc)的调用来分配内存,继而调用构造函数,完成对象的构造。
但是在调用构造函数的过程中,如果发生异常,则会调用static void operator delete(void* rawMemory,ostream& os) throw()来收回已分配的内存,并恢复旧观。
如果没发生异常,也就是一个对象正常构造完毕,则在delete w;调用的时候,调用的则是在StandardNewDeleteForms中定义的static void operator delete(void* pMemory) throw()来完成对象的析构和内存的回收工作。
因此在自定义一个专属版本的placement new的时候,一定要自定义一个带有相同额外参数的placement delete来处理出现异常情况的内存回收。
为了防止在一个类中自定义的placement new遮掩正常的operator new版本,可以采取将正常版本的operator new和operator new定义在基类的办法,由自定义placement new和placement delete的类来继承。
当operator new抛出异常之前以反映一个未满足的内存需求之前,会先调用称为new-handler的客户指定的错误处理函数。
new_handler是一个typedef的函数指针:typedef void ( *new_handler )( );
定制模板基类来定制operator new和set_new_handler函数的办法如下:
class NewHandlerHolder { public: explicit NewHandlerHolder(new_handler nh):handler(nh) {} ~NewHandlerHolder() {set_new_handler(handler);} private: new_handler handler; }; template <typename T> class NewHandlerSupport { public: static new_handler set_new_handler(new_handler p) throw(); static void* operator new(size_t size) throw(bad_alloc); private: static new_handler currentHandler; }; template <typename T> new_handler NewHandlerSupport<T>::currentHandler=NULL; template <typename T> new_handler NewHandlerSupport<T>::set_new_handler(new_handler p) throw() { new_handler oldHandler=currentHandler; currentHandler=p; return oldHandler; } template <typename T> void* NewHandlerSupport<T>::operator new(size_t size) throw(bad_alloc) { NewHandlerHolder h(set_new_handler(currentHandler)); return ::operator new(size); } class Widget:public NewHandlerSupport<Widget> { public: Widget() {cout<<"Widget::Widget()"<<endl;} ~Widget() {cout<<"Widget::~Widget()"<<endl;} }; void OutOfMemory() { cerr<<"Unable to satisfy request for memory."<<endl; abort(); } int _tmain(int argc, _TCHAR* argv[]) { Widget::set_new_handler(OutOfMemory); Widget *pw=new Widget(); delete pw; return 0; }
其中采用了用对象管理资源的手法。template机制为会每一个T生成一份currentHandler。
注意的一件事情:operator new不止一次尝试分配内存,并在每次失败后调用new-handling函数,只有当new-handling函数的指针是null,operator new才会抛出异常。
new-handler一般做以下几件事情:让更多内存可用,安装另一个new-handler,卸除new-handler,抛出bad_alloc异常,或是承认失败而直接return。
Item 50 Understand when it makes sense to repace new and delete.了解new和delete的合理替换时机。
一般有如下理由:
(1)用来检测运用上的错误。
(2)为了强化效能。
(3)为了收集使用上的统计数据。
(4)为了降低缺省内存管理其带来的空间额外开销。
(5)为了弥补缺省分配器中的非最佳齐位。
(6)为了将相关对象成簇集中。placement new。
(7)为了获得非传统的行为。
但无论有何种理由,请确认的确想替换掉编译器提供的operator new。
Item 51 Adhere to convention when writing new and delete.编写new和delete时需固守常规。
operator new应该内含一个无穷循环,并在其中尝试分配内存,如果它无法满足内存需求,就该调用new-handler。
operator new应该有能力处理0byte申请。class专属版本则应该处理“比正确大小更大的(错误)申请”。
//不太明白的地方。
operator delete应该在收到null指针时不做任何事。class专属版本则还应该处理“比正确大小更大的(错误)申请”。
Item 52 Write placement delete if you write placement new.写了placement new也要写placement delete。
class StandardNewDeleteForms { public: static void* operator new(size_t size) throw(bad_alloc) { return ::operator new(size); } static void operator delete(void* pMemory) throw() { cout<<"standard delete(void* pMemory)"<<endl; ::operator delete(pMemory); } static void* operator new(size_t size,void* ptr) throw() { return ::operator new(size,ptr); } static void operator delete(void* pMemory,void* ptr) throw() { cout<<"standard delete(size_t size,void* ptr)"<<endl; ::operator delete(pMemory,ptr); } static void* operator new(size_t size,const nothrow_t& nt) throw() { return ::operator new(size,nt); } static void operator delete(void *pMemory,const nothrow_t&) throw() { cout<<"standard delete(void *pMemory,const nothrow_t&)"<<endl; ::operator delete(pMemory); } }; class Widget : public StandardNewDeleteForms { public: using StandardNewDeleteForms::operator new; using StandardNewDeleteForms::operator delete; static void* operator new(size_t size,ostream& os) throw(bad_alloc) { os<<"my operator new"<<endl; return operator new(size); } static void operator delete(void* rawMemory,ostream& os) throw() { os<<"my operator delete"<<endl; operator delete(rawMemory); } }; int _tmain(int argc, _TCHAR* argv[]) { Widget *w=new (cerr)Widget; delete w; return 0; }
Widget *w=new (cerr)Widget;
这样的一句代码,引起的是在Widget类内定义的static void* operator new(size_t size,ostream& os) throw(bad_alloc)的调用来分配内存,继而调用构造函数,完成对象的构造。
但是在调用构造函数的过程中,如果发生异常,则会调用static void operator delete(void* rawMemory,ostream& os) throw()来收回已分配的内存,并恢复旧观。
如果没发生异常,也就是一个对象正常构造完毕,则在delete w;调用的时候,调用的则是在StandardNewDeleteForms中定义的static void operator delete(void* pMemory) throw()来完成对象的析构和内存的回收工作。
因此在自定义一个专属版本的placement new的时候,一定要自定义一个带有相同额外参数的placement delete来处理出现异常情况的内存回收。
为了防止在一个类中自定义的placement new遮掩正常的operator new版本,可以采取将正常版本的operator new和operator new定义在基类的办法,由自定义placement new和placement delete的类来继承。
相关文章推荐
- 【effective c++读书笔记】【第8章】定制new和delete(1)
- 【effective c++读书笔记】【第8章】定制new和delete(1)
- Effective C++笔记(11)—定制new和delete
- Effective C++读书笔记---定制new和delete
- 定制new和delete(Cpp Operators of new and delete)
- Effective C++ 第八章(定制new和delete)
- Effective C++ 8. 定制 new 和 delete
- 8.定制new和delete
- Effective C++读书笔记 第八部分 定制new和delete
- [Effective C++]定制new和delete
- 定制自己的new和delete:operator new 和 operator delete
- Effective C++(八)定制new和delete
- 【effective c++】定制new和delete
- Effective C++(八)定制new和delete
- 第八章 定制new和delete
- Effective C++ —— 定制new和delete(八)
- 《Effective C++ 3》08 定制new/delete和其他 条款:49-55
- C++(8)定制new和delete
- 《Effective C++第三版》读书笔记——定制new和delete
- 【effective c++读书笔记】【第8章】定制new和delete(2)