您好,欢迎访问三七文档
当前位置:首页 > 行业资料 > 冶金工业 > C++定制new和delete
定制new和deleteCustomizingnewanddelete当计算环境(例如Java和.NET)夸耀自己内置“垃圾回收能力”的当今,C++对内存管理的纯手工法也许看起来有些老气。但是许多苛刻的系统程序开发人员之所以选择C++,就是因为它允许他们手工管理内存。这样的开发人员研究并学习他们的软件使用内存的行为特征,然后修改分配和归还工作,以求获得所建置的系统的最佳效率(包括时间和空间)。这样做的前提是,了解C++内存管理例程的行为。这正是本章焦点。这场游戏的两个主角是分配例程和归还例程(allocationanddeallocationroutines,也就是operatornew和operatordelete),配角是new-handler,这是当operatornew无法满足客户的内存需求时所调用的函数。多线程环境下的内存管理,遭受单线程系统不曾有过的挑战。由于heap是一个可被改动的全局性资源,因此多线程系统充斥着发狂访问这一类资源的raceconditions(竞速状态)出现机会。本章多个条款提及使用可改动之static数据,这总是会令线程感知(thread-aware)程序员高度警戒如坐针毡。如果没有适当的同步控制(synchronization),一旦使用无锁(lock-free)算法或精心防止并发访问(concurrentaccess)时,调用内存例程可能很容易导致管理heap的数据结构内容败坏。我不想一再提醒你这些危险,我只是打算在这里提一下,然后假设你会牢记在心。另外要记住的是,operatornew和operatordelete只适合用来分配单一对象。Arrays所用的内存由operatornew[]分配出来,并由operatordelete[]归还(注意两个函数名称中的[])。除非特别表示,我所写的每一件关于operatornew和operatordelete的事也都适用于operatornew[]和operatordelete[]。最后请注意,STL容器所使用的heap内存是由容器所拥有的分配器对象(allocatorobjects)管理,不是被new和delete直接管理。本章不讨论STL分配器。了解new-handler的行为Understandthebehaviorofthenew-handler当operatornew无法满足某一内存分配需求时,它会抛出异常。以前它会返回一个null指针,某些旧式编译器目前也还那么做。你还是可以取得旧行为(有那么几分像啦),但是本条款最后才会进行这项讨论。当operatornew抛出异常以反映一个未获满足的内存需求之前,它会先调用一个客户指定的错误处理函数,一个所谓的new-handler。(这其实并不是全部事实。operatornew真正做的事情稍微更复杂些。)为了指定这个“用以处理内存不足”的函数,客户必须调用set_new_handler,那是声明于new的一个标准程序库函数:namespacestd{typedefvoid(*new-handler)();new-handlerset_new_handler(new_handlerp)throw();}如你所见,new-handler是个typedef,定义出一个指针指向函数,该函数没有参数也不返回任何东西。Set_new_handler则是“获得一个new_handler并返回一个new_handler”的函数。set_new_handler声明式尾端的“throw()”是一份异常明细,表该函数不抛出任何异常——虽然事实更有趣些。set_new_handler的参数是个指针,指向operatornew无法分配足够内存时该被调用的函数。其返回值也是个指针,指向set_new_handler被调用前正在执行(但马上就要被替换)的那个new-handler函数。你可以这样使用Set_new_handler://以下是当operatornew无法分配足够内存时,该被调用的函数voidoutOfMem(){std::cerr”Unabletosatisfyrequestformemory\n”;std::abort();}intmain(){std::set_new_handler(outOfMem);int*pBigDataArray=newint[100000000L];...}就本例而言,如果operatornew无法为100,000,000个整数分配足够空间,outOfMem会被调用,于是程序在发出一个信息之后夭折(abort)。(顺带一提,如果在写出错误信息至cerr过程期间必须动态分配内存,考虑会发生什么事......)当operatornew无法满足内存申请时,它会不断调用new_handler函数,直到找到足够内存。引起反复调用的代码在effectiveC++条款51中,这里的高级描述已足够获得一个结论,那就是一个设计良好的new-handler函数必须做以下事情:让更多的内存可被使用。这便造成了operatornew内的下一次内存分配动作可能成功。实现此策略的一个做法是,程序一开始执行就分配一大块内存,而后当new-handler第一次被调用,将它们释还给程序使用。安装另一个new-handler。如果目前这个new-handler无法取得更多可用内存,或许它知道另外哪个new-handler有此能力。果真如此,目前这个new-handler就可以安装另外那个new-handler以替换自己(只要调用Set_new_handler)。下次当operatornew调用new-handler,调用的将是最新安装的那个。(这个旋律的变奏之一是让new-handler修改自己的行为,于是当它下次被调用,就会做某些不同的事。为达此目的,做法之一是令new-handler修改“会影响new-handler行为”的static数据、namespace数据或global数据。)卸除new-handler,也就是将null指针传给set_new_handler。一旦没有安装任何new-handler,operatornew会在内存分配不成功时抛出异常。抛出bad_alloc(或派生自bad_alloc)的异常。这样的异常不会被operatornew捕捉,因此会被传播到内存所求处。不返回,通常调用abort或exit。这些选择让你在实现new-handler函数时拥有很大弹性。
本文标题:C++定制new和delete
链接地址:https://www.777doc.com/doc-2901635 .html