Part8:定制new和delete
2016-07-07 11:08
155 查看
当计算环境(例如java和.net)夸耀自己内置“垃圾回收能力”的当今,C++对内存管理的纯手工方法看起来老土。但是许多苛刻的系统程序开发人员之所以选择C++,就是因为它允许他们手工管理内存。
这样做的前提是,了解C++内存管理例程的行为。这部分的两个主角是分配例程和归还例程(allocation and deallocation routines,也就是operator new and operator delete),配角是new-handler,这是当operator new无法满足客户的内存需求时所调用的函数。
需要注意:STL容器所使用的heap内存是由容器所拥有的分配器对象管理,不是被new和delete直接管理。
set_new_handler()方法在new分配内存失败时系统自动调用该函数,没有出错不会进行调用
如果想对不同的类在分配类存是出现了错误,从而调用不同的处理函数,我们可以把函数的定义放入不同的类定义中。
比如:假设你打算处理Widget class的内存分配失败情况,首先你必须登录“当operator new无法为一个Widget对象分配足够内存时”调用的函数,所以需要声明一个类型为new_handler的static成员,用以指向class Widget的new_handler。
Widget的定义像如下:
最后Widget的operator new 做如下事情。
1 调用标准set_new_hanlder,告知Widget的错误处理函数,这会将Widget的new_handler安装为global new-handler。
2 调用global operator new,执行实际之内存分配,如果分配失败,global operator new会调用Widget 的 new-hanler,因为那个函数才刚被安装为global new-handler。如果global operator new最终无法分配足够内存,会抛出一个bad_alloc异常。
Rule50:了解new和delete的合理替换时机
Understand when it makes sense to replace new and delete。
为什么有时想要替换编译器提供的operator new 或operator delete呢?
下面是三个最常见的理由:
1、用来检测运用上的错误
通过在分配类存的后面追加额外空间放置特定的byte patterns,即签名,operator deletes便得以检查上述签名是否原封不动,若否就表示在分配区的某个生命时间点发生了变化。
2、为了强化效果。
编译器所带的operator new和operator delete主要用于一般目的,如果你对你的程序的动态内存运用形态有深刻的了解,通常可以发现,定制版的operator new和operator delete性能胜过缺省版本,他们的表现经常是快,且需要的内存比较少。
3、为了收集使用上的统计数据。
Rule51:编写new和delete时需要固守常规
adhere to convention when writing new and delete.
operator new的返回值十分单纯,如果他有能力供应客户申请的内存,就返回一个指针指向那块内存。如果没有那个能力,就使用set_new_handler,并抛出一个bad_alloc异常。
Widget *pw = new Widget;
这句语句共有两个函数被调用:一个是用以分配内存的operator new,一个是Widget的default构造函数。
这样做的前提是,了解C++内存管理例程的行为。这部分的两个主角是分配例程和归还例程(allocation and deallocation routines,也就是operator new and operator delete),配角是new-handler,这是当operator new无法满足客户的内存需求时所调用的函数。
需要注意:STL容器所使用的heap内存是由容器所拥有的分配器对象管理,不是被new和delete直接管理。
set_new_handler()方法在new分配内存失败时系统自动调用该函数,没有出错不会进行调用
#include<iostream> using namespace std; void fun() { cout<<"error occur when allocate heap"<<endl; } int _tmain(int argc, _TCHAR* argv[]) { std::new_handler p = fun; set_new_handler(p); long* pBigDataArray = new long[1000000000L]; getchar(); return 0; }
如果想对不同的类在分配类存是出现了错误,从而调用不同的处理函数,我们可以把函数的定义放入不同的类定义中。
比如:假设你打算处理Widget class的内存分配失败情况,首先你必须登录“当operator new无法为一个Widget对象分配足够内存时”调用的函数,所以需要声明一个类型为new_handler的static成员,用以指向class Widget的new_handler。
Widget的定义像如下:
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 Widget::currentHandler = 0; std::new_handler Widget::set_new_handler(std::new_handler p) throw() { std::new_handler oldHandler = currentHandler; currentHandler = p; return oldHandler; }
最后Widget的operator new 做如下事情。
1 调用标准set_new_hanlder,告知Widget的错误处理函数,这会将Widget的new_handler安装为global new-handler。
2 调用global operator new,执行实际之内存分配,如果分配失败,global operator new会调用Widget 的 new-hanler,因为那个函数才刚被安装为global new-handler。如果global operator new最终无法分配足够内存,会抛出一个bad_alloc异常。
Rule50:了解new和delete的合理替换时机
Understand when it makes sense to replace new and delete。
为什么有时想要替换编译器提供的operator new 或operator delete呢?
下面是三个最常见的理由:
1、用来检测运用上的错误
通过在分配类存的后面追加额外空间放置特定的byte patterns,即签名,operator deletes便得以检查上述签名是否原封不动,若否就表示在分配区的某个生命时间点发生了变化。
2、为了强化效果。
编译器所带的operator new和operator delete主要用于一般目的,如果你对你的程序的动态内存运用形态有深刻的了解,通常可以发现,定制版的operator new和operator delete性能胜过缺省版本,他们的表现经常是快,且需要的内存比较少。
3、为了收集使用上的统计数据。
Rule51:编写new和delete时需要固守常规
adhere to convention when writing new and delete.
operator new的返回值十分单纯,如果他有能力供应客户申请的内存,就返回一个指针指向那块内存。如果没有那个能力,就使用set_new_handler,并抛出一个bad_alloc异常。
Widget *pw = new Widget;
这句语句共有两个函数被调用:一个是用以分配内存的operator new,一个是Widget的default构造函数。
相关文章推荐
- 在Load average 高的情况下如何鉴别系统瓶颈
- 关于mysql 删除数据后物理空间未释放(转载)
- Linux gcc编译器常用命令和使用
- C#实现的AES加密解密完整实例
- Android Studio实现代码混淆
- UVa 10566 - Crossed Ladders
- 大小和尺寸的概念
- 手把手教你使用Git
- 指针形参
- Junit4单元测试之高级用法
- PHP之:序列化和反序列化-serialize()和unserialize()
- [go语言学习指南]
- bootstrap学习笔记-导航和导航条
- Square
- SpringMVC+Mybatis整合搭建
- HDU 1078 FatMouse and Cheese
- Linux开发工具(gcc,gdb,make,shell)——linux中静态库和动态库的区别(三)
- windows的20%带宽限制的误区
- java redis demo关于List<Integer>,List<String>
- 并发学习心得