c改善程序设计技术的个有效做法实用.pptx
《c改善程序设计技术的个有效做法实用.pptx》由会员分享,可在线阅读,更多相关《c改善程序设计技术的个有效做法实用.pptx(171页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、C+新标准新的类型bool 有两个值true,false.typedefintbool;constboolfalse=0;constbooltrue=1;第1页/共171页新的转型动作static_cast(expression)/将表达式expression转为type类型const_cast(expression)/将常数类型expression转为非常数类型dynamic_cast(expression)/安全向下转型见39reinterpret_cast(expression)/函数指针类型转换不常用第2页/共171页1.尽量以const和inline取代#define#define是
2、一个宏,只能被预处理,而不被编译,用它定义的常量甚至不被编译器看见,因此不能发现使用中的错误。用#define定义一个简单函数,必须为每一个参数加上一个括号,容易造成错误。用内联函数高效准确。第3页/共171页define ratio 1.653/编译器看不见ratio,只看见1.653/一旦出错,不会报告constdoubleratio=1.653;constchar*constname=“ScottMeyers”;/字符串常量第4页/共171页In Class 常量 用静态变量类内声明,类外定义。classEngineerConstantsprivate:staticconstdouble
3、Factor;constdoubleEngineerConstants:Factor=1.35;第5页/共171页2.尽量以取代scanfprintf函数不能扩充用来输入输出自定义类型的变量。cinix;coutix;可以扩展,方便得多改变旧有的C习惯(shifting from C to C+)1.尽量以const和inline取代#define#define 是一个宏,只能被预处理,而不被编译,用它定义的常量甚至不被编译器看见,因此不能发现使用中的错误。用#define定义一个简单函数,必须为每一个参数加上一个括号,容易造成错误。用内联函数高效准确。第6页/共171页3.尽量以new和de
4、lete取代malloc和freemalloc和free不能调用构造函数,析构函数new和delete则可。不能混用newdeletemallocfree必要用C库函数时检查是否用到malloc重新用new和delete改过。第7页/共171页4.尽量使用C+风格的注释形式/*/要保证成对出现,不小心错一大片。/好看好读可以混合使用当心!definelight_speed3e8/m/sec(inavacum)第8页/共171页内存管理(memory management)new隐式调用构造函数,delete隐式调用析构函数,可以重载operatornew和operatordelete.不小心运
5、用new和delete会导致各种错误。第9页/共171页5.使用相同形式的new和deletestring*a=newstring10;deletea;/出错deletea;/正确string*b=newstring;deleteb;/出错deleteb;/正确第10页/共171页typedef string addresslines4;string*a=newaddresslines;deletea;/出错deletea;/正确不要对数组类型用typedef,不容易记住用哪一种delete第11页/共171页6.记得在析构函数中以delete对付指针成员如果类中有指针数据成员,在每个构造函数
6、中为指针成员配置内存,否则将它初始化为0(NULL指针)。若构造函数中用new配置了内存,一定要在析构函数中用delete释放在赋值运算重载时要将原有指针的内存删除,重新分配内存。要在析构函数中删除这个指针。第12页/共171页不要用delete删除一个未完成初始化的指针,不要删除一个未分配内存的指针。不要delete从一个类外面传来的指针。第13页/共171页7.为内存不足的状况预作准备不能认为“检查内存是否分配成功”是多此一举。否则会出现严重后果。必须建立一个错误处理策略。当operatornew无法满足需求时,在抛出异常之前,会调用一个内存不足处理函数newhandler,这个函数由头文
7、件提供。第14页/共171页typedef void(*new_handle)();new_handlerset_new_handler(new_handlerp)throw();new_handler是一个函数指针,无参,无返回值。函数set_new_handler用来配置new_handler,参数和返回值都是函数指针,new_handler类型。它确定新的new_handler函数(参数),保留旧的new_handler函数(返回)。第15页/共171页可以自定义新的new_handler函数,用set_new_handler确认。voidnomoreMemory()cerr“Unabl
8、etosatisfyformemeoryn”abort();/exitintmain()set_new_handler(nomoreMemory);int*pBigDataArray=newint100000000;当operatornew无法配置10000000个整数空间时,系统调用nomoreMemory,然后结束。第16页/共171页设计new_handler函数,令其完成如下任务:-让更多的内存可用。预留一块内存,new_handler第一次被调用时释放,同时发出警告。安装新的new_handler以取代自己。new_handler中调用C+标准库函数set_new_handler即可
9、。卸载这个new_handler,返回NULL指针,并抛出bad_alloc(或其继承)类型的异常。直接调用abort或exit终止程序。第17页/共171页C+不支持class中专用的new_handler,但仍可以在一个class中重载operator new,和set_new_handler函数,让它调用特定的new_handler函数,而不用系统给出的全局new_handler。classXpublic:static new_handler set_new_handler(new_handler p);staticvoid*operatornew(size_tsiz);private:
10、staticnew_handlercurrentHandler;第18页/共171页new_handlerX:currentHandler;/初始化为0new_handlerX:set_new_handler(new_handlerp)new_handleroldHandler=currentHandler;/保留当前new_handlercurrentHandler=p;/再设置当前new_handlerreturnoldHandler;第19页/共171页void*X:operator new(size_t size)newHandlerglobalHandler=std:set_new_
11、handler(currentHandler);/配置新new_handler保存globalHandlervoid*memory;trymemory=:opratornew(size);/试分配内存catch(std:bad_alloc&)std:set_new_handler(globalHandler);/恢复原有处理方法throw;/传播异常std:set_new_handler(globalHandler):/恢复原有处理方法returnmemory;/调用一次特定处理方法,用毕恢复第20页/共171页/应用voidnomoreMemory();X:set_new_handler(n
12、omoreMemory);X*px1=newX;/如果内存分配失败,调用nomoreMemory()string*ps=newstring;/如果内存分配失败,调用globalHandlerX:set_new_handler(0);X*px2=newX;/如果内存分配失败,立即抛出异常第21页/共171页可以做一个混合风格基类允许“设定class专属new_handler”templateclassNewHandlerSupportpublic:static new_handler set_ new_handler(new_handler p);staticvoid*operatornew(s
13、ize_tsiz);private:staticnew_handlercurrentHandler;第22页/共171页templatenew_handlerNewHandlerSupport:set_new_handler(new_handlerp)new_handleroldHandler=currentHandler;/保留当前new_handlercurrentHandler=p;/再设置当前new_handlerreturnoldHandler;第23页/共171页templatevoid*NewHandlerSupport:operator new(size_t size)newH
14、andlerglobalHandler=std:set_new_handler(currentHandler);/配置新new_handler保存globalHandlervoid*memory;trymemory=:opratornew(size);/试分配内存catch(std:bad_alloc&)std:set_new_handler(globalHandler);/恢复原有处理方法throw;/传播异常std:set_new_handler(globalHandler):/恢复原有处理方法returnmemory;第24页/共171页new_handler NewHandlerSup
15、port :currentHandler;/初始化为0classX:publicNewHandlerSupport/不必声明set_new_handler和operatornew类X不必改动原有的程序代码,就可以继续运作。第25页/共171页1993年前C+要求operatornew在无法满足内存需求时返回0,新标准则是抛出一个bad_alloc类型异常。失败便转为0的传统被保留为“nothrow”不抛出异常。头文件中定义了一个nothrow对象classWidget;Widget*pw1=newWidget;/如果失败抛出std:bad_alloc异常if(pw1=0)/无效widget*w
16、p2=new(nothrow)Widget;/如果失败,返回0if(wp2=0)/有效第26页/共171页8.撰写operator new和operator delete时应遵守的公约当你有必要重载operatornew时,你的new函数的行为应该与系统原有的new函数的行为保持一致。应该有正确的返回值:返回一个指针指向分配的内存。如果内存不足,抛出一个bad_alloc类型的异常。不能覆盖系统原有的new函数。第27页/共171页/new 函数的伪码void*operatornew(size_tsize)if(size=0)size=1;/将0内存需求,看成1内存需求,避免与无内存混淆whi
17、le(true)/无穷循环直到内存被分配或抛出异常attempttoallocatesizebytes;if(theallocationwassuccessful)return(apointertothememory);new_handleglobalHandle=set_new_handler(0)/利用NULL,找出目前的错误处理函数set_new_handler(globalHandler);/重新设定为原本的函数if(globalHandler)(*globalHandler)()elsethrowstd:bad_alloc();第28页/共171页无穷循环可以让更多的内存可用,或安装
18、一个不同的new_handler,或卸载new_handler,或抛出一个异常,或直接结束程序。第29页/共171页operator new 可以被继承,但要小心,否则会导致问题classBasepublic:staticvoid*opratornew(size_tsize);;classDerived:publicBase;/导出类中没有operatornew函数Derived*p=newDerived;/调用Base类中的operatornew出错这里导出类内存比基类要大。第30页/共171页改进的办法:void*operatornew(size_tsize)if(size!=sizeof
19、(Base)return:opratornew(size);/回到标准operatornew函数第31页/共171页重写operator deletevoidoperatordelete(void*rawMemory)if(rawMemory=0)return;/与C+标准delete保持一致DeallocatethememorypointedtobyrawMemory;return;第32页/共171页/member版classBasepublic:staticvoid*operatornew(size_tsize);static void operator delete(void*rawM
20、emory,size_t size);第33页/共171页voidBase:operatordelete(void*rawMemory,size_tsize);if(rawMemory=0)return;if(size!=sizeof(Base)/如果大小错误:operatordelete(rawMemory);/用标准版delete处理return;deallocatethememorypointedtobyrawmeMemory;return;第34页/共171页9.避免覆盖new的正规形式解决办法(1)再写的一个专用的operatornew函数,让它支持正规的newclassXpubli
21、c:voidf();staticvoid*operatornew(size_tsize,new_handlerp);staticvoid*operatornew(sise_tsize)return:operatornew(size);第35页/共171页X*p1=new(specialErrorHandler)X;/调用X:operatornew(size_tsize,new_handlerp);X*p2=newX;/调用X:operatornew(size_tsize);(2)为operatornew的每一个参数提供默认值(缺省值)第36页/共171页10.如果写了一个operator ne
22、w 不要忘记写一个operator delete需要动态分配大量小额内存空间的应用程序,有时需要重载operatornew。classAirplaneRep;classAirplanepublic:private:AirplaneRep*rep;/唯一数据成员是指针;第37页/共171页Airplane*p=new Airplane;/要求内存不大分配的内存比实际所需要的内存要大,这是为了delete这块内存时,系统能知道其大小。pa 纪录内存大小的 数据Airplane 对象所需的 内存 为了节省内存需要定制内存管理。第38页/共171页定制内存管理。classAirplanepublic:
23、staticvoid*operatornew(size_tsize);static void operator delete(void*deadObject,size_t size);private:unionAirplaneRep*rep;Airplane*next;/两个指针公用一个内存staticconstintBLOCK_SIZE;staticAirplane*headOfFreeList;/用链表配置一片内存,整个类只须一个链;第39页/共171页void*Airplane:operatornew(size_tsize);if(size!=sizeof(Airplane)return
24、:operatornew(size);Airplane*p=headOfFreeList;/p指向链表头if(p)headOfFreeList=p-next;/表头后移,p可用elseAirplane*newBlock=static_cast(:operatornew(BLOCK_SIZE*sizeof(Airplane);for(inti=1;iBLOCKSIZE-1;+i)/保留第一块newBlocki.next=&newBlocki+1;newBlockBLOCK_SIZE-1.next=0;/置表尾p=newBlok;/p可用headOfFreeList=&newBlock1;retu
25、rnp;第40页/共171页只有当:operatornew失败时,这里的operatornew才失败。这时:operatornew会调用new_handler直到抛出异常,因此我们不需要再写一次new_handler处理具体实现文件中要先对静态成员初始化,Airplane*Airplane:headOfFreeList;/headOfFreeList置0constintAirplane:BLOCK_SIZE=512;这个版本的operatornew可以运作良好,速度快过两个数量级。第41页/共171页还要在Airplane类中写一个operatordeletevoidAirplane:oper
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 改善 程序设计 技术 有效 做法 实用
限制150内