欢迎来到淘文阁 - 分享文档赚钱的网站! | 帮助中心 好文档才是您的得力助手!
淘文阁 - 分享文档赚钱的网站
全部分类
  • 研究报告>
  • 管理文献>
  • 标准材料>
  • 技术资料>
  • 教育专区>
  • 应用文书>
  • 生活休闲>
  • 考试试题>
  • pptx模板>
  • 工商注册>
  • 期刊短文>
  • 图片设计>
  • ImageVerifierCode 换一换

    (精品)改善程序设计技术的50个有效做法.ppt

    • 资源ID:85125474       资源大小:426.50KB        全文页数:172页
    • 资源格式: PPT        下载积分:16金币
    快捷下载 游客一键下载
    会员登录下载
    微信登录下载
    三方登录下载: 微信开放平台登录   QQ登录  
    二维码
    微信扫一扫登录
    下载资源需要16金币
    邮箱/手机:
    温馨提示:
    快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。
    如填写123,账号就是123,密码也是123。
    支付方式: 支付宝    微信支付   
    验证码:   换一换

     
    账号:
    密码:
    验证码:   换一换
      忘记密码?
        
    友情提示
    2、PDF文件下载后,可能会被浏览器默认打开,此种情况可以点击浏览器菜单,保存网页到桌面,就可以正常下载了。
    3、本站不支持迅雷下载,请使用电脑自带的IE浏览器,或者360浏览器、谷歌浏览器下载即可。
    4、本站资源下载后的文档和图纸-无水印,预览文档经过压缩,下载后原文更清晰。
    5、试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。

    (精品)改善程序设计技术的50个有效做法.ppt

    改善程序设计技术的50个有效做法第二版2002.3ScottMeyers侯捷译如何完成较好的设计如何避免常见的问题如何提高效率的一些准则不是放之四海而皆准的唯一真理C+新标准新的类型bool 有两个值true,false.typedefintbool;constboolfalse=0;constbooltrue=1;新的转型动作static_cast(expression)/将表达式expression转为type类型const_cast(expression)/将常数类型expression转为非常数类型dynamic_cast(expression)/安全向下转型见39reinterpret_cast(expression)/函数指针类型转换不常用1.尽量以const和inline取代#define#define是一个宏,只能被预处理,而不被编译,用它定义的常量甚至不被编译器看见,因此不能发现使用中的错误。用#define定义一个简单函数,必须为每一个参数加上一个括号,容易造成错误。用内联函数高效准确。defineratio1.653/编译器看不见ratio,只看见1.653/一旦出错,不会报告constdoubleratio=1.653;constchar*constname=“ScottMeyers”;/字符串常量InClass常量用静态变量类内声明,类外定义。classEngineerConstantsprivate:staticconstdoubleFactor;constdoubleEngineerConstants:Factor=1.35;2.尽量以取代scanfprintf函数不能扩充用来输入输出自定义类型的变量。cinix;coutix;可以扩展,方便得多改变旧有的改变旧有的C习惯(习惯(shifting from C to C+)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)内存管理内存管理(memory management)new隐式调用构造函数,delete隐式调用析构函数,可以重载operatornew和operatordelete.不小心运用new和delete会导致各种错误。5.使用相同形式的new和deletestring*a=newstring10;deletea;/出错deletea;/正确string*b=newstring;deleteb;/出错deleteb;/正确typedefstringaddresslines4;string*a=newaddresslines;deletea;/出错deletea;/正确不要对数组类型用typedef,不容易记住用哪一种delete6.记得在析构函数中以delete对付指针成员如果类中有指针数据成员,在每个构造函数中为指针成员配置内存,否则将它初始化为0(NULL指针)。若构造函数中用new配置了内存,一定要在析构函数中用delete释放在赋值运算重载时要将原有指针的内存删除,重新分配内存。要在析构函数中删除这个指针。不要用delete删除一个未完成初始化的指针,不要删除一个未分配内存的指针。不要delete从一个类外面传来的指针。7.为内存不足的状况预作准备不能认为“检查内存是否分配成功”是多此一举。否则会出现严重后果。必须建立一个错误处理策略。当operatornew无法满足需求时,在抛出异常之前,会调用一个内存不足处理函数newhandler,这个函数由头文件提供。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“Unabletosatisfyformemeoryn”abort();/exitintmain()set_new_handler(nomoreMemory);int*pBigDataArray=newint100000000;当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中重载中重载operator new,和和set_new_handler函数,让它函数,让它调用特定的调用特定的new_handler函数,而不用系统给出的全局函数,而不用系统给出的全局new_handler。classXpublic:static new_handler set_new_handler(new_handler p);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;trymemory=: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”templateclassNewHandlerSupportpublic:static new_handler set_ new_handler(new_handler p);staticvoid*operatornew(size_tsiz);private:staticnew_handlercurrentHandler;templatenew_handlerNewHandlerSupport:set_new_handler(new_handlerp)new_handleroldHandler=currentHandler;/保留当前new_handlercurrentHandler=p;/再设置当前new_handlerreturnoldHandler;templatevoid*NewHandlerSupport:operator new(size_t size)newHandlerglobalHandler=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;new_handlerNewHandlerSupport:currentHandler;/初始化为0classX:publicNewHandlerSupport/不必声明set_new_handler和operatornew类X不必改动原有的程序代码,就可以继续运作。1993年前C+要求operatornew在无法满足内存需求时返回0,新标准则是抛出一个bad_alloc类型异常。失败便转为0的传统被保留为“nothrow”不抛出异常。头文件中定义了一个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(0)/利用NULL,找出目前的错误处理函数set_new_handler(globalHandler);/重新设定为原本的函数if(globalHandler)(*globalHandler)()elsethrowstd:bad_alloc();无穷循环可以让更多的内存可用,或安装一个不同的new_handler,或卸载new_handler,或抛出一个异常,或直接结束程序。operatornew可以被继承,但要小心,否则会导致问题classBasepublic:staticvoid*opratornew(size_tsize);;classDerived:publicBase;/导出类中没有operatornew函数Derived*p=newDerived;/调用Base类中的operatornew出错这里导出类内存比基类要大。改进的办法:void*operatornew(size_tsize)if(size!=sizeof(Base)return:opratornew(size);/回到标准operatornew函数重写operatordeletevoidoperatordelete(void*rawMemory)if(rawMemory=0)return;/与C+标准delete保持一致DeallocatethememorypointedtobyrawMemory;return;/member版classBasepublic:staticvoid*operatornew(size_tsize);static void operator delete(void*rawMemory,size_t size);voidBase:operatordelete(void*rawMemory,size_tsize);if(rawMemory=0)return;if(size!=sizeof(Base)/如果大小错误:operatordelete(rawMemory);/用标准版delete处理return;deallocatethememorypointedtobyrawmeMemory;return;9.避免覆盖new的正规形式解决办法(1)再写的一个专用的operatornew函数,让它支持正规的newclassXpublic:voidf();staticvoid*operatornew(size_tsize,new_handlerp);staticvoid*operatornew(sise_tsize)return:operatornew(size);X*p1=new(specialErrorHandler)X;/调用X:operatornew(size_tsize,new_handlerp);X*p2=newX;/调用X:operatornew(size_tsize);(2)为operatornew的每一个参数提供默认值(缺省值)10.如果写了一个operatornew不要忘记写一个operatordelete需要动态分配大量小额内存空间的应用程序,有时需要重载operatornew。classAirplaneRep;classAirplanepublic:private:AirplaneRep*rep;/唯一数据成员是指针;Airplane*p=newAirplane;/要求内存不大分配的内存比实际所需要的内存要大,这是为了delete这块内存时,系统能知道其大小。pa纪录内存大小的数据Airplane对象所需的内存为了节省内存需要定制内存管理。定制内存管理。classAirplanepublic:staticvoid*operatornew(size_tsize);static void operator delete(void*deadObject,size_t size);private:unionAirplaneRep*rep;Airplane*next;/两个指针公用一个内存staticconstintBLOCK_SIZE;staticAirplane*headOfFreeList;/用链表配置一片内存,整个类只须一个链;void*Airplane:operatornew(size_tsize);if(size!=sizeof(Airplane)return: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;returnp;只有当:operatornew失败时,这里的operatornew才失败。这时:operatornew会调用new_handler直到抛出异常,因此我们不需要再写一次new_handler处理具体实现文件中要先对静态成员初始化,Airplane*Airplane:headOfFreeList;/headOfFreeList置0constintAirplane:BLOCK_SIZE=512;这个版本的operatornew可以运作良好,速度快过两个数量级。还要在Airplane类中写一个operatordeletevoidAirplane:operatordelete(void*deadObject,size_tsize)if(deadObject=0)return;if(size!=sizeof(Airplane):operatordelete(deadObject);/与operatornew处理保持一致return;Airplane*carcass=static_cast(deadObject);carcass-next=headOfFreeList;HeadOfFreeList=carcass;如果没有定义相应的delete函数,而使用了原有的delete,结果会出现意想不到的错误,有时是严重的错误。如果用member版本不要忘记定义virtual析构函数。这里的delete函数没有memory leak 问题。问题。这是因为用了memorypool一次分配一块内存,逐步使用逐步释放,不必再专门释放memorypool.定义一个memorypool类,使每一个pool对象都是一个内存配置器。classPoolpublic:Pool(size_tn);void*alloc(size_tn);/为一个对象配置足够/的内存遵循operatornew的规矩voidfree(void*p,size_tn);/将p的内存送回/pool遵循operatordelete的规矩pool();/释放pool中所有内存;用Pool对象来配置内存,当被销毁时,配置的内存自动被释放。于是memoryleak就可以避免。classAirplanepublic:staticvoid*operatornew(size_tsize);staticvoidoperatordelete(void*p,size_tsize);private:AirplaneRep*rep;staticPoolmemPool;/Airplane的memorypool;inlinevoidAirline:operatornew(size_tsize)returnmemPool.alloc(size);inlinevoidAirline:operatordelete(void*p,size_tsize)memPool.free(p,size);为Airplane的memPool初始化,要放在Airplane类实现的文件里PoolAirplane:memPool(sizeof(Airplane);构造函数、析构函数和赋值运算符构造函数、析构函数和赋值运算符构造函数、析构函数和赋值运算用来产生一个新对象并初始化,撤销一个对象并收回占有的内存,为已有的对象赋一个新值。不能有错,必须将他们彻底搞清楚。11.class内有成员指针并动态配置内存时,一定要有拷贝构造函数,赋值运算符重载classStringpublic:String(constchar*value);String();/没有拷贝构造函数,/也没有赋值运算符重载private:char*data;String:String(constchar*value)if(value)data=newcharstrlen(value)+1;strcopy(data,value);elsedata=newchar1;*data=“0”;inlineString:String()deletedata;Stringa(“Hello”);Stringb(“World”);b=a;HelloWorldabdatadata由于没有自定义的赋值函数,只能用C+产生的默认赋值函数,它简单地将b的成员指针data指向a.data,引起字符串“World”占有的内存遗失。而且a.data与b.data指向同一个内存,其中一个被析构时另一个就丢失了。拷贝构造函数用来传值,voiddonothing(Stringla)Strings=“thetruthisoutofthere”;donothing(s);当函数donothing完成任务后,参数s所含的指针被析构,la被删除。即便la不再使用,将来又一次析构la会造成问题。解决的办法就是自己定义拷贝构造函数,赋值函数重载。如果确信永不使用这些函数,把他们定义为私有函数,而且不实现。一旦出错,编译器会给出错误提示。12构造函数中尽量以初始化代替赋值一个类中的const成员数据和reference引用数据只能被初始化,不能被赋值。即便没有const成员数据和reference引用数据,初始化也比赋值效率高。构造函数分两个阶段实现:1.数据成员初始化。2.调用构造函数。数据成员赋值要调用构造函数,再调用赋值函数,做两次调用影响效率。初始化也容易维护,修改。有一种例外:一个类内有大量数据成员时,赋值比初始化效率高。classManyDataMbspublic:ManyDataMbs()ManyDataMbs(constManyDataMbs&x);private:inta,b,c,d,e,f,g,h;doublei,j,k,l,m;voidinit();/用来将数据成员初始化,不做他用;voidManyDataMbs:init()a=b=c=d=e=f=g=h=1;i=j=k=l=m=0;ManyDataMbs:ManyDataMbs()init();ManyDataMbs:ManyDataMbs(constManyDataMbs&x)init();静态数据成员staticclassmember不应该在构造函数中初始化。静态数据成员只能初始化一次,不能初始化多次。12.数据成员初始化的次序应该和类内声明的次序相同templateclassArray/有上下界的数组public:Array(intlowBound,inthighBound);private:vectordata;/数组数据存储于一个vector对象data中size_tsize;/数组中元素的个数intlBound,hBound;/上下界;templateArray:Array(intlowBound,inthighBound):size(highBound-lowBound+1),lBound(lowBound),hBound(highBound),data(size)实际初始化中,data先被初始化,然后size,lBound,hBound.这样数组中,究竟有多少个元素无法确定。基类成员总是比导出类先初始化。多重继承时初始化的先后次序要十分小心。14.总是让基类拥有虚析构函数总是让基类拥有虚析构函数一个军事应用软件classEnemyTargetpublic:EnemyTarget()+numTargets;EnemyTarget(constEnemyTarget&)+numTargets;EnemyTarget()-numTargets;staticsize_tnumberOfTargets()returnnumTargets;virtualbooldestroy();/摧毁敌方目标是否成功private:staticsize_tnumTargets;/对象计数器;size_tEnemyTarget:numTargets;/静态成员初始化为0,放在类外classEnemyTank:publicEnemyTargetpublic:EnemyTank()+numTanks;EnemyTank(constEnemyTank&)+numTanks;EnemyTank()-numTanks;staticsize_tnumberOfTanks()returnnumTanks;virtualbooldestroy();/摧毁敌方坦克是否成功private:staticsize_tnumTanks;/敌方坦克计数器;EnemyTarget*targetPtr=newEnemyTank;deletetargetPtr;/未定义,计数出错,影响战斗胜败解决办法,把EnemyTarget类中的析构函数定义为virtual即可。几乎所有的基类都有虚函数,只要有一个虚函数,就要把析构函数定义为虚函数。没有虚函数的类,有继承派生类对象析构,也要定义虚析构函数。但虚函数会增加内存开销。完全不必要时不要用虚析构函数。声明一个抽象类,可以加一个纯虚析构函数。15.让让operator=返回返回*this的引用的引用referenceC语言中operator=的原型C&C:operator=(constC&);charx,y,z;x=y=z=a;x,operator=(y.operator=(z.operator=a);z.operator=的返回值是y.operator=的实参。他们应该有相同的类型。但不要让operator=返回void类型,const类型Strin&String:operator=(constString&rhs)return*this;/返回一个引用指向左侧对象Strin&String:operator=(constString&rhs)returnrhs;/返回一个引用指向右侧对象,错误后一个返回值,编译器无法编译,无法返回const类型.如果参数中去掉const变成:Strin&String:operator=(String&rhs);X=a;/无法编译rhs应该是一个变量。结论:必须返回*this;16.在在operator=中为所有的数据成员赋值中为所有的数据成员赋值基类中这不成问题,在派生类中要小心。正确的赋值运算Derived&Derived:operator=(constDrived&rhs)if(this=&rhs)return*this;Base:operator=(rhs);/调用基类的赋值运算data=rhs.data;return*this;Derived&Derived:operator=(constDrived&rhs)if(this=&rhs)return*this;static_cast(*this)=rhs;/*this强制转换成基类的引用赋值基类成员data=rhs.data;return*this;拷贝构造函数中要调用基类构造函数。用第一种方法在在operator=中检查是否中检查是否“自己赋值给自己自己赋值给自己”classX;Xa;X&b=a;/b是a的别名(aliasing)a=b;/自己赋值给自己合法在赋值函数中要特别谨慎的处理自己的别名赋值给自己的问题。提高效率先做检查,一发现自己赋值给自己立即返回。导出类的赋值运算重载中一定要先检查,可以节省许多工作确保正确性赋值运算通常要先将左边对象的资源释放,再行赋值。如果有自己赋值给自己的现象,这个资源可能丢失,不可挽回了。如何判断两个对象是同一个对象?不是对象的内容相同,而是看他们的地址是否相同。X&X:operator=(constX&rhs)if(this=&rhs)return*this;aliasing问题不限于赋值运算内,只要用到指针或引用,就可能出现。这时我们就要当心,不要误删了有用的资源。类和函数的设计和申明类和函数的设计和申明设计一个高效率的类型(class型别),必须先回答下列问题对象如何产生和销毁?确定构造函数和析构函数的设计。对象的初始化和赋值有什么不同?决定构造函数和赋值函数的设计。对象如何传值决定拷贝构造函数的设计确定合法的范围 成员数据的定义域确定做什么检查,何时抛出异常判断是否能从已有的类继承如果能继承,注意受基类哪些约束,哪些要用虚函数。允许那种类型转换构造函数可以用作隐式类型转换,显式类型转换要自定义。新类型需要哪些运算和函数确定class的接口。哪些运算和函数必须禁用放到private成员中。新类型的对象可调用哪些函数确定公有成员函数,保护成员函数,私有成员函数。是否通用类型确定是否要用类模板18努力让接口完满(努力让接口完满(complete)且最小化且最小化客户端接口客户端接口(clientinterface)指公有成员,一般只有公有函数,不要有公有数据。完满接口完满接口 允许客户做合理要求的任意事情。最小化接口最小化接口尽量让函数个数最少。不能有功能重叠的函数。太多函数不容易被理解,不易维护,浪费资源。如果增加一个函数,使新类型更方便使用,就可以增加。T&operator(intindex);/传回数组的一个元素,可读,可写constT&operator(intindex)const;/传回数组的一个元素,可读,不可写19区分成员函数、非成员函数区分成员函数、非成员函数 和友元函数和友元函数成员函数可以动态绑定,可以用virtual非成员函数不能用virtual,非成员函数能不做友元尽量不做友元函数。非成员函数要调用类中私有数据成员或私有函数,则一定要声明为友元。不要让operaor成为类的成员函数,必要时作友元。要让函数式左边对象做类型转换,就不能做成员函数。例子classcomplexcomplexoperator*(complexrhs)const;private:floatx,y;complexa(1,2),b(1.5,4);a=a*b;/正确a=a*2;/可以a=2*a;/出错只能声明为非成员函数constcomplexoperator*(constcomplex&lhs,constcomplex&rhs);20避免将数据成员设置为公有数据避免将数据成员设置为公有数据让公有成员都是函数,可以保持一致性。将数据成员声明为私有成员或保护成员,可以确保数据的安全。21尽可能使用尽可能使用const使用const可以让编译器知道某值不能改变,编译器会确保这个条件不会被改变。constchar*p;/指针,指向常值字符串char*constp;/常指针,指向固定地址,地址内字符串不一定是常量constchar*constp;/常指针,指向固定地址,内置常字符串constchr*p;charconst*p;/意义相同函数中函数中const 可以修饰传回值,参数,成员可以修饰传回值,参数,成员函数时甚至可以修饰整个函数。函数时甚至可以修饰整个函数。函数返回值用 const,可以改善函数的安全性,和效率。T&A:operator(intindex);/传回数组的一个元素,可读,可写Aa(8);couta2;a2=b;/正确constT&A:operator(intindex);/传回数组的一个元素,可读,不可写Aa(8);couta2;/正确a2=b;/错误constcomplexoperator*(constcomplex&lhs,constcomplex&rhs);complexa,b,c;(a*b)=c;/不允许参数用const可以保证参数值不变,让编译器作检查。const成员函数保证this指针不变。classApublic:intlength()const;private:intsize;;intA:length()constif(size0)return0;/错误不能改变任何数据成员returnsize;新C+标准新增保留字mutableclassApublic:intlength()const;private:mutableintsize;/可以在任何地点被改动,/即使在const成员函数中;intA:length()constif(size0)return0;/正确returnsize;22尽量使用引用参数传址尽量使用引用参数传址pass by reference拷贝构造函数用来传值passbyvalue,为函数的参数传值,为函数的返回值传值。传值要占用许多资源。classPersonpublic:Person();Person();private:stringname,address;classstudent:publicPersonpublic:student();student();private:stringschoolname,schoolAddress;studentreturnstudent(students)returns;studentplato;returnstudent(plato);函数调用中copy构造函数被调用两次,将plato传给参数s,再将函数值返回,析构函数调用两次,析构s,析构函数返回值。更有甚者,基类Person的构造函数也要调用两次。student对象中两个string数据对象要构造,基类Person中两个string数据对象也要构造,plato给s构造四次,返回传值构造四次总共调用12次构造函数,当然还有12次析构函数要调用。免除这些不当成本,改用引用参数传址byreferenceconststudent&returnstudent(conststudent&s)returns;引用参数传址byreference不调用任何构造函数析构函数。虚函数的引用参数是基类时,实际传入派生类对象时可以调用派生类的函数。传值参数没有这样的功能。引用参数要注意别名(aliasing)问题。23当你必须传回当你必须传回objebct(传值传值)时不要传时不要传址址(引用)引用)尽可能让事情简单,但不要过于简单。A.Einstein尽可能让事情有效率,但不要过于有效率。C+函数必须传回一个对象,就不要传址不要返回引用。不能传回一个不存在的地址,不能传回函数中产生的局部对象的地址。const complex operator*(const complex&lhs,constcomplex&rhs)complextemp(lhs.x*rhs.x-lhs.y*rhs.y,lhs.x*rhs.y+lhs.y*rhs.x);returntemp;&错误。返回值地址指向局部对象,与局部对象同名,运算执行完毕,局部对象被析构,返回值指向一个不存在的地址。const complex&operator*(const complex&lhs,constcomplex&rhs)complex*temp(lhs.x*rhs.x-lhs.y*rhs.y,lhs.x*rhs.y+lhs.y*rhs.x);return*temp;指针temp被析构,内存已丢失。constcomplex&operator*(constcomplex&lhs,constcomplex&rhs)complex*temp=newcomplex(lhs.x*rhs.x-lhs.y*rhs.y,lhs.x*rhs.y+lhs.y*rhs.x);return*temp;指针temp没有析构,将来谁来析构呢。内存可能丢失。complexone(1),two(2),three(3),four(4);complexproduct;product=one*two*th

    注意事项

    本文((精品)改善程序设计技术的50个有效做法.ppt)为本站会员(gsy****95)主动上传,淘文阁 - 分享文档赚钱的网站仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知淘文阁 - 分享文档赚钱的网站(点击联系客服),我们立即给予删除!

    温馨提示:如果因为网速或其他原因下载失败请重新下载,重复下载不扣分。




    关于淘文阁 - 版权申诉 - 用户使用规则 - 积分规则 - 联系我们

    本站为文档C TO C交易模式,本站只提供存储空间、用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。本站仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知淘文阁网,我们立即给予删除!客服QQ:136780468 微信:18945177775 电话:18904686070

    工信部备案号:黑ICP备15003705号 © 2020-2023 www.taowenge.com 淘文阁 

    收起
    展开