改善程序设计技术的50个有效做法.ppt
《改善程序设计技术的50个有效做法.ppt》由会员分享,可在线阅读,更多相关《改善程序设计技术的50个有效做法.ppt(172页珍藏版)》请在三一办公上搜索。
1、改善程序设计技术的50个有效做法 第二版2002.3 Scott Meyers 侯 捷 译,如何完成较好的设计如何避免常见的问题如何提高效率的一些准则不是放之四海而皆准的唯一真理,C+新标准新的类型bool,有两个值true,false.typedef int bool;const bool false=0;const bool true=1;,新的转型动作,static_cast(expression)/将表达式expression转为type类型const_cast(expression)/将常数类型expression转为非常数类型dynamic_cast(expression)/安全向
2、下转型 见39reinterpret_cast(expression)/函数指针类型转换 不常用,1.尽量以const和inline取代#define,#define 是一个宏,只能被预处理,而不被编译,用它定义的常量甚至不被编译器看见,因此不能发现使用中的错误。用#define定义一个简单函数,必须为每一个参数加上一个括号,容易造成错误。用内联函数高效准确。,define ratio 1.653/编译器看不见ratio,只看见1.653/一旦出错,不会报告,const double ratio=1.653;const char*const name=“Scott Meyers”;/字符串常量
3、,In Class 常量,用静态变量类内声明,类外定义。class EngineerConstants private:static const double Factor;const double EngineerConstants:Factor=1.35;,2.尽量以取代,scanf printf 函数 不能扩充用来输入输出自定义类型的变量。cinix;coutix;可以扩展,方便得多,改变旧有的C习惯(shifting from C to C+)尽量以const和inline取代#define#define 是一个宏,只能被预处理,而不被编译,用它定义的常量甚至不被编译器看见,因此不能发
4、现使用中的错误。用#define定义一个简单函数,必须为每一个参数加上一个括号,容易造成错误。用内联函数高效准确。,3.尽量以new和delete取代malloc和free,malloc 和free 不能调用构造函数,析构函数 new 和delete则可。不能混用new delete malloc free 必要用C库函数时检查是否用到malloc重新用new和delete改过。,4.尽量使用C+风格的注释形式,/*/要保证成对出现,不小心错一大片。/好看好读 可以混合使用当心!define light_speed 3e8/m/sec(in a vacum),内存管理(memory manag
5、ement),new 隐式调用构造函数,delete 隐式调用析构函数,可以重载operator new和operator delete.不小心运用new 和delete会导致各种错误。,5.使用相同形式的new和delete,string*a=new string10;delete a;/出错delete a;/正确string*b=new string;delete b;/出错delete b;/正确,typedef string addresslines4;,string*a=new addresslines;delete a;/出错delete a;/正确不要对数组类型用typedef
6、,不容易记住用哪一种delete,6.记得在析构函数中以delete对付指针成员,如果类中有指针数据成员,在每个构造函数中为指针成员配置内存,否则将它初始化为0(NULL指针)。若构造函数中用new配置了内存,一定要 在析构函数中用delete释放在赋值运算重载时要将原有指针的内存删除,重新分配内存。要在析构函数中删除这个指针。,不要用delete删除一个未完成初始化的指针,不要删除一个未分配内存的指针。不要delete从一个类外面传来的指针。,7.为内存不足的状况预作准备,不能认为“检查内存是否分配成功”是多此一举。否则会出现严重后果。必须建立一个错误处理策略。当operator new 无
7、法满足需求时,在抛出异常之前,会调用一个内存不足处理函数new handler,这个函数由头文件提供。,typedef void(*new_handle)();,new_handler set_new_handler(new_handler p)throw();new_handler是一个函数指针,无参,无返回值。函数set_new_handler用来配置new_handler,参数和返回值都是函数指针,new_handler类型。它确定新的new_handler函数(参数),保留旧的new_handler函数(返回)。,可以自定义新的new_handler函数,用set_new_handle
8、r确认。,void nomoreMemory()cerr“Unable to satisfy for memeoryn”abort();/exit int main()set_new_handler(nomoreMemory);int*pBigDataArray=new int100000000;当operator new 无法配置10000000个整数空间时,系统调用nomoreMemory,然后结束。,设计new_handler函数,令其完成如下任务:,-让更多的内存可用。预留一块内存,new_handler第一次被调用时释放,同时发出警告。安装新的new_handler以取代自己。new
9、_handler中调用C+标准库函数set_new_handler即可。卸载这个new_handler,返回NULL指针,并抛出bad_alloc(或其继承)类型的异常。直接调用abort或exit终止程序。,C+不支持class中专用的new_handler,但仍可以在一个class中重载operator new,和set_new_handler函数,让它调用特定的new_handler函数,而不用系统给出的全局new_handler。,class X public:static new_handler set_new_handler(new_handler p);static void*o
10、perator new(size_t siz);private:static new_handler currentHandler;,new_handler X:currentHandler;/初始化为0new_handler X:set_new_handler(new_handler p)new_handler oldHandler=currentHandler;/保留当前new_handler currentHandler=p;/再设置当前new_handler return oldHandler;,void*X:operator new(size_t size),newHandler g
11、lobalHandler=std:set_new_handler(currentHandler);/配置新new_handler 保存globalHandler void*memory;try memory=:oprator new(size);/试分配内存 catch(std:bad_alloc/调用一次特定处理方法,用毕恢复,/应用,void nomoreMemory();X:set_new_handler(nomoreMemory);X*px1=new X;/如果内存分配失败,调用nomoreMemory()string*ps=new string;/如果内存分配失败,调用globalH
12、andlerX:set_new_handler(0);X*px2=new X;/如果内存分配失败,立即抛出异常,可以做一个混合风格基类允许“设定class专属new_handler”,templateclass NewHandlerSupport public:static new_handler set_ new_handler(new_handler p);static void*operator new(size_t siz);private:static new_handler currentHandler;,template,new_handler NewHandlerSupport
13、:set_new_handler(new_handler p)new_handler oldHandler=currentHandler;/保留当前new_handler currentHandler=p;/再设置当前new_handler return oldHandler;,template,void*NewHandlerSupport:operator new(size_t size)newHandler globalHandler=std:set_new_handler(currentHandler);/配置新new_handler 保存globalHandler void*memor
14、y;try memory=:oprator new(size);/试分配内存 catch(std:bad_alloc,new_handler NewHandlerSupport:currentHandler;/初始化为0,class X:public NewHandlerSupport/不必声明set_new_handler和operator new类X 不必改动原有的程序代码,就可以继续运作。,1993年前C+要求operator new在无法满足内存需求时返回0,新标准则是抛出一个bad_alloc类型异常。失败便转为0的传统被保留为“nothrow”不抛出异常。头文件中定义了一个noth
15、row对象 class Widget;Widget*pw1=new Widget;/如果失败抛出std:bad_alloc异常 if(pw1=0)/无效 widget*wp2=new(nothrow)Widget;/如果失败,返回0 if(wp2=0)/有效,8.撰写operator new和operator delete时应遵守的公约,当你有必要重载operator new时,你的new函数的行为应该与系统原有的new函数的行为保持一致。应该有正确的返回值:返回一个指针指向分配的内存。如果内存不足,抛出一个bad_alloc类型的异常。不能覆盖系统原有的new函数。,/new 函数的伪码,v
16、oid*operator new(size_t size)if(size=0)size=1;/将0内存需求,看成1内存需求,避免与无内存混淆 while(true)/无穷循环 直到内存被分配 或抛出异常 attempt to allocate size bytes;if(the allocation was successful)return(a pointer to the memory);new_handle globalHandle=set_new_handler(0)/利用NULL,找出目前的错误处理函数 set_new_handler(globalHandler);/重新设定为原本的
17、函数 if(globalHandler)(*globalHandler)()else throw std:bad_alloc();,无穷循环可以让更多的内存可用,或安装一个不同的new_handler,或卸载new_handler,或抛出一个异常,或直接结束程序。,operator new 可以被继承,但要小心,否则会导致问题,class Base public:static void*oprator new(size_t size);;class Derived:public Base;/导出类中没有operator new 函数Derived*p=new Derived;/调用Base类中
18、的operator new出错这里导出类内存比基类要大。,改进的办法:,void*operator new(size_t size)if(size!=sizeof(Base)return:oprator new(size);/回到标准operator new函数,重写operator delete,void operator delete(void*rawMemory)if(rawMemory=0)return;/与C+标准delete保持一致 Deallocate the memory pointed to by rawMemory;return;,/member版,class Base p
19、ublic:static void*operator new(size_t size);static void operator delete(void*rawMemory,size_t size);,void Base:operator delete(void*rawMemory,size_t size);if(rawMemory=0)return;if(size!=sizeof(Base)/如果大小错误:operator delete(rawMemory);/用标准版delete处理 return;deallocate the memory pointed to by rawmeMemor
20、y;return;,9.避免覆盖new的正规形式,解决办法(1)再写的一个专用的operator new函数,让它支 持正规的new class X public:void f();static void*operator new(size_t size,new_handler p);static void*operator new(sise_t size)return:operator new(size);,X*p1=new(specialErrorHandler)X;/调用X:operator new(size_t size,new_handler p);X*p2=new X;/调用X:o
21、perator new(size_t size);(2)为operator new的每一个参数提供默认值(缺省值),10.如果写了一个operator new 不要忘记写一个operator delete,需要动态分配大量小额内存空间的应用程序,有时需要重载operator new。class AirplaneRep;class Airplane public:private:AirplaneRep*rep;/唯一数据成员是指针;,Airplane*p=new Airplane;/要求内存不大,分配的内存比实际所需要的内存要大,这是为了delete 这块内存时,系统能知道其大小。,pa,为了节
22、省内存需要定制内存管理。,定制内存管理。,class Airplane public:static void*operator new(size_t size);static void operator delete(void*deadObject,size_t size);private:union AirplaneRep*rep;Airplane*next;/两个指针公用一个内存 static const int BLOCK_SIZE;static Airplane*headOfFreeList;/用链表配置一片内存,整个类只须一个链;,void*Airplane:operator new
23、(size_t size);if(size!=sizeof(Airplane)return:operator new(size);Airplane*p=headOfFreeList;/p指向链表头 if(p)headOfFreeList=p-next;/表头后移,p可用 else Airplane*newBlock=static_cast(:operator new(BLOCK_SIZE*sizeof(Airplane);for(int i=1;iBLOCKSIZE-1;+i)/保留第一块 newBlocki.next=,只有当:operator new失败时,这里的operator new
24、才失败。这时:operator new会调用new_handler直到抛出异常,因此我们不需要再写一次new_handler处理具体实现文件中要先对静态成员初始化,Airplane*Airplane:headOfFreeList;/headOfFreeList置0 const int Airplane:BLOCK_SIZE=512;这个版本的operator new 可以运作良好,速度快过两个数量级。,还要在Airplane类中写一个operator delete void Airplane:operator delete(void*deadObject,size_t size)if(dead
25、Object=0)return;if(size!=sizeof(Airplane):operator delete(deadObject);/与operator new处理保持一致 return;Airplane*carcass=static_cast(deadObject);carcass-next=headOfFreeList;HeadOfFreeList=carcass;,如果没有定义相应的delete函数,而使用了原有的delete,结果会出现意想不到的错误,有时是严重的错误。如果用member版本不要忘记定义virtual 析构函数。这里的delete函数没有memory leak
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 改善 程序设计 技术 50 有效 做法
链接地址:https://www.31ppt.com/p-4784498.html