C++中的内存管理——对effective c++第二章的总结
2007-07-17 17:22
429 查看
operator new在无法完成内存分配请求时会抛出异常(以前的做法一般是返回0),也可以当内存分配请求不能满足时,调用你预先指定的一个出错处理函数。即当operator new不能满足请求时,会在抛出异常之前调用客户指定的该出错处理函数——一般称为new-handler函数。指定出错处理函数时要用到set_new_handler函数,set_new_handler的输入参数是operator new分配内存失败时要调用的出错处理函数的指针,返回值是set_new_handler没调用之前就已经在起作用的旧的出错处理函数的指针。它在头文件<new>里大致是象下面这样定义的:
typedef void (*new_handler)();
new_handler set_new_handler(new_handler p) throw();
可以象下面这么使用set_new_handler函数:
之所以有时需要定义自己的operator new和operator delete?最主要的原因是为了效率。缺省版本的operator new是一种通用型的内存分配器,它必须可以分配任意大小的内存块。同样,operator delete也要可以释放任意大小的内存块。operator delete想弄清它要释放的内存有多大,就必须知道当初operator new分配的内存有多大。所以在new所返回的内存里预先附带一些额外信息,用来指明被分配的内存块的大小。如果软件运行在一个内存很宝贵的环境中,且需要分配多个很小的类对象,就承受不起这种奢侈的内存分配方案了。 具体的实现是先让缺省operator new分配一些大块的原始内存,每块的大小都足以容纳很多个小的类对象。该类对象的内存块就取自这些大的内存块。当前没被使用的内存块被组织成链表(称为自由链表)以备将来该类对象使用。在实际开发中,还可以把这种固定大小内存的分配器封装起来,从而可以更加方便地使用(参考effective c++条款10)。
typedef void (*new_handler)();
new_handler set_new_handler(new_handler p) throw();
可以象下面这么使用set_new_handler函数:
// function to call if operator new can't allocate enough memory void nomorememory() { cerr << "unable to satisfy request for memory/n"; abort(); } int main() { set_new_handler(nomorememory); int *pbigdataarray = new int[100000000]; ... } 注意operator new内部包含一个无限循环,实际上会不只一次地尝试着去分配内存,它要在每次失败后调用出 错处理函数。所以一个设计得好的new-handler函数必须实现下面功能中的一种。 ·产生更多的可用内存。这将使operator new下一次分配内存的尝试有可能获得成功。实施这一策略的一 个方法是:在程序启动时分配一个大的内存块,然后在第一次调用new-handler时释放。释放时伴随着一些对用 户的警告信息,如内存数量太少,下次请求可能会失败,除非又有更多的可用空间。 ·安装另一个不同的new-handler函数。如果当前的new-handler函数不能产生更多的可用内存,可能它会 知道另一个new-handler函数可以提供更多的资源。这样的话,当前的new-handler可以安装另一个new-handler 来取代它(通过调用set_new_handler)。下一次operator new调用new-handler时,会使用最近安装的那个。(这 一策略的另一个变通办法是让new-handler可以改变它自己的运行行为,那么下次调用时,它将做不同的事。方 法是使new-handler可以修改那些影响它自身行为的静态或全局数据。) ·卸除new-handler。也就是传递空指针给set_new_handler。没有安装new-handler,operator new分配内 存不成功时就会抛出一个标准的std::bad_alloc类型的异常。 ·抛出std::bad_alloc或从std::bad_alloc继承的其他类型的异常。这样的异常不会被operator new捕捉, 所以它们会被送到最初进行内存请求的地方。(抛出别的不同类型的异常会违反operator new异常规范。规范中 的缺省行为是调用abort,所以new-handler要抛出一个异常时,一定要确信它是从std::bad_alloc继承来的。 ·没有返回。典型做法是调用abort或exit。abort/exit可以在标准c库中找到。 c++不支持专门针对于类的new-handler函数,而且也不需要。你可以自己来实现它,只要在每个类中提供自己版 本的set_new_handler和operator new。类的set_new_handler可以为类指定new-handler(就象标准的 set_new_handler指定全局new-handler一样)。类的operator new则保证为类的对象分配内存时用类的new-handler 取代全局new-handler。因为operator new对类类型的对象分配内存失败时,每次都必须调用出错处理函数,所以 要在类里声明一个new_handler类型的静态成员。
之所以有时需要定义自己的operator new和operator delete?最主要的原因是为了效率。缺省版本的operator new是一种通用型的内存分配器,它必须可以分配任意大小的内存块。同样,operator delete也要可以释放任意大小的内存块。operator delete想弄清它要释放的内存有多大,就必须知道当初operator new分配的内存有多大。所以在new所返回的内存里预先附带一些额外信息,用来指明被分配的内存块的大小。如果软件运行在一个内存很宝贵的环境中,且需要分配多个很小的类对象,就承受不起这种奢侈的内存分配方案了。 具体的实现是先让缺省operator new分配一些大块的原始内存,每块的大小都足以容纳很多个小的类对象。该类对象的内存块就取自这些大的内存块。当前没被使用的内存块被组织成链表(称为自由链表)以备将来该类对象使用。在实际开发中,还可以把这种固定大小内存的分配器封装起来,从而可以更加方便地使用(参考effective c++条款10)。
相关文章推荐
- 【c++Primer】第二章掌握C++总结
- 数据结构与算法分析(C++第三版)第二章问题总结
- c++面试总结(+网上收入)--内存管理(
- Effective C++ 总结2 内存管理 (条款5 - 10)
- Effective c++ 第二章总结
- c++学习历程(3)之 第二章基础知识总结
- c++面试总结(+网上收入)--内存管理(
- 第二章 C++基础篇之最全面的C/C++编码规范总结
- Effective C++ 总结1 从C转向C++(条款1 - 4)
- C/C++ 内存管理总结
- C/C++内存管理总结
- 第二章:内存管理(Effective C++ Second Edition 读书笔记)
- 对自定义的C++内存管理的一些总结!
- Effective C++ 总结1 从C转向C++(条款1 - 4)
- C++版数据结构第二章线性表总结
- imooc 学习总结——离港篇:C++内存管理
- boost shared_ptr 及C++内存管理的一些总结
- Effective C++ 总结1 从C转向C++(条款1 - 4)
- C++继承与面向对象 Effective C++总结(item 32 - 39)
- c/c++ 内存管理与分配总结