改善程序设计的50各有效方法

整理文档很辛苦,赏杯茶钱您下走!

免费阅读已结束,点击下载阅读编辑剩下 ...

阅读已结束,您可以下载文档离线阅读编辑

资源描述

改善程序设计技术的50个有效做法第二版2002.3ScottMeyers侯捷译如何完成较好的设计如何避免常见的问题如何提高效率的一些准则不是放之四海而皆准的唯一真理C++新标准新的类型bool有两个值true,false.typedefintbool;constboolfalse=0;constbooltrue=1;新的转型动作static_casttype(expression)//将表达式expression转为type类型const_casttype(expression)//将常数类型expression转为非常数类型dynamic_casttype(expression)//安全向下转型见39reinterpret_casttype(expression)//函数指针类型转换不常用1.尽量以const和inline取代#define#define是一个宏,只能被预处理,而不被编译,用它定义的常量甚至不被编译器看见,因此不能发现使用中的错误。用#define定义一个简单函数,必须为每一个参数加上一个括号,容易造成错误。用内联函数高效准确。#defineratio1.653//编译器看不见ratio,只看见1.653//一旦出错,不会报告constdoubleratio=1.653;constchar*constname=“ScottMeyers”;//字符串常量InClass常量用静态变量类内声明,类外定义。classEngineerConstants{private:staticconstdoubleFactor;……};constdoubleEngineerConstants::Factor=1.35;2.尽量以iostream取代stdio.hscanfprintf函数不能扩充用来输入输出自定义类型的变量。cinix;coutix;可以扩展,方便得多改变旧有的C习惯(shiftingfromCtoC++)1.尽量以const和inline取代#define#define是一个宏,只能被预处理,而不被编译,用它定义的常量甚至不被编译器看见,因此不能发现使用中的错误。用#define定义一个简单函数,必须为每一个参数加上一个括号,容易造成错误。用内联函数高效准确。3.尽量以new和delete取代malloc和freemalloc和free不能调用构造函数,析构函数new和delete则可。不能混用newdeletemallocfree必要用C库函数时检查是否用到malloc重新用new和delete改过。4.尽量使用C++风格的注释形式/*……*/要保证成对出现,不小心错一大片。//好看好读可以混合使用当心!#definelight_speed3e8//m/sec(inavacum)内存管理(memorymanagement)new隐式调用构造函数,delete隐式调用析构函数,可以重载operatornew和operatordelete.不小心运用new和delete会导致各种错误。5.使用相同形式的new和deletestring*a=newstring[10];……deletea;//出错delete[]a;//正确string*b=newstring;……delete[]b;//出错deleteb;//正确typedefstringaddresslines[4];string*a=newaddresslines;……deletea;//出错delete[]a;//正确不要对数组类型用typedef,不容易记住用哪一种delete6.记得在析构函数中以delete对付指针成员如果类中有指针数据成员,在每个构造函数中为指针成员配置内存,否则将它初始化为0(NULL指针)。若构造函数中用new配置了内存,一定要在析构函数中用delete释放在赋值运算重载时要将原有指针的内存删除,重新分配内存。要在析构函数中删除这个指针。不要用delete删除一个未完成初始化的指针,不要删除一个未分配内存的指针。不要delete从一个类外面传来的指针。7.为内存不足的状况预作准备不能认为“检查内存是否分配成功”是多此一举。否则会出现严重后果。必须建立一个错误处理策略。当operatornew无法满足需求时,在抛出异常之前,会调用一个内存不足处理函数newhandler,这个函数由头文件new提供。typedefvoid(*new_handle)();new_handlerset_new_handler(new_handlerp)throw();new_handler是一个函数指针,无参,无返回值。函数set_new_handler用来配置new_handler,参数和返回值都是函数指针,new_handler类型。它确定新的new_handler函数(参数),保留旧的new_handler函数(返回)。可以自定义新的new_handler函数,用set_new_handler确认。voidnomoreMemory(){cerr“Unabletosatisfyformemeory\n”abort();//exit}intmain(){set_new_handler(nomoreMemory);int*pBigDataArray=newint[100000000];……}当operatornew无法配置10000000个整数空间时,系统调用nomoreMemory,然后结束。设计new_handler函数,令其完成如下任务:--让更多的内存可用。预留一块内存,new_handler第一次被调用时释放,同时发出警告。–安装新的new_handler以取代自己。new_handler中调用C++标准库函数set_new_handler即可。–卸载这个new_handler,返回NULL指针,并抛出bad_alloc(或其继承)类型的异常。–直接调用abort或exit终止程序。C++不支持class中专用的new_handler,但仍可以在一个class中重载operatornew,和set_new_handler函数,让它调用特定的new_handler函数,而不用系统给出的全局new_handler。classX{public:staticnew_handlerset_new_handler(new_handlerp);staticvoid*operatornew(size_tsiz);private:staticnew_handlercurrentHandler;};new_handlerX::currentHandler;//初始化为0new_handlerX::set_new_handler(new_handlerp){new_handleroldHandler=currentHandler;//保留当前new_handlercurrentHandler=p;//再设置当前new_handlerreturnoldHandler;}void*X::operatornew(size_tsize){newHandlerglobalHandler=std::set_new_handler(currentHandler);//配置新new_handler保存globalHandlervoid*memory;try{memory=::opratornew(size);//试分配内存}catch(std::bad_alloc&){std::set_new_handler(globalHandler);//恢复原有处理方法throw;//传播异常}std::set_new_handler(globalHandler)://恢复原有处理方法returnmemory;}//调用一次特定处理方法,用毕恢复//应用voidnomoreMemory();X::set_new_handler(nomoreMemory);X*px1=newX;//如果内存分配失败,调用nomoreMemory()string*ps=newstring;//如果内存分配失败,调用globalHandlerX::set_new_handler(0);X*px2=newX;//如果内存分配失败,立即抛出异常可以做一个混合风格基类允许“设定class专属new_handler”templateclassTclassNewHandlerSupport{public:staticnew_handlerset_new_handler(new_handlerp);staticvoid*operatornew(size_tsiz);private:staticnew_handlercurrentHandler;};templateclassTnew_handlerNewHandlerSupportT::set_new_handler(new_handlerp){new_handleroldHandler=currentHandler;//保留当前new_handlercurrentHandler=p;//再设置当前new_handlerreturnoldHandler;}templateclassTvoid*NewHandlerSupportT::operatornew(size_tsize){newHandlerglobalHandler=std::set_new_handler(currentHandler);//配置新new_handler保存globalHandlervoid*memory;try{memory=::opratornew(size);//试分配内存}catch(std::bad_alloc&){std::set_new_handler(globalHandler);//恢复原有处理方法throw;//传播异常}std::set_new_handler(globalHandler)://恢复原有处理方法returnmemory;}new_handlerNewHandlerSupportT::currentHandler;//初始化为0classX:publicNewHandlerSupportX{……//不必声明set_new_handler和operatornew}类X不必改动原有的程序代码,就可以继续运作。1993年前C++要求operatornew在无法满足内存需求时返回0,新标准则是抛出一个bad_alloc类型异常。失败便转为0的传统被保留为“nothrow”不抛出异常。new头文件中定义了一个nothrow对象classWidget{……};Widget*pw1=newWidget;//如果失败抛出std::bad_alloc异常if(pw1==0)……//无效widget*wp2=new(nothrow)Widget;//如果失败,返回0if(wp2==0)……//有效8.撰写operatornew和operatordelete时应遵守的公约当你有必要重载operatornew时,你的new函数的行为应该与系统原有的new函数的行为保持一致。应该有正确的返回值:返回一个指针指向分配的内存。如果内存不足,抛出一个bad_alloc类型的异常。不能覆盖系统原有的new函数。//new函数的伪码void*operatornew(size_tsize){if(size==0){size=1;}//将0内存需求,看成1内存需求,避免与无内存混淆while(true)//无穷循环直到内存被分配或抛出异常{attempttoallocatesizebytes;if(theallocationwassuccessful)return(apointertothememory);new_handleglobalHandle=set_new_handler

1 / 172
下载文档,编辑使用

©2015-2020 m.777doc.com 三七文档.

备案号:鲁ICP备2024069028号-1 客服联系 QQ:2149211541

×
保存成功