Effective C++读书笔记---实现

大多数情况下,适当提出你的classes(和class templates)定义以及functions(和function templates)声明,是花费最多心力的地方。一旦正确完成它们,相应的实现大多直截了当。尽管如此,还是有些东西需要小心。太快定义变量可能造成效率上的拖延;过度使用转型(casts)可能导致代码变慢又难维护,可能招来微妙难解的错误;返回对象“内部数据之号令牌(handles)”可能会破坏封装并留给客户虚吊号码牌(dangling handles);未考虑异常带来的冲击则可能导致资源泄漏和数据败坏;过度热心地inlining可能会引起代码膨胀;过度耦合(coupling)则可能导致让人不满意的冗长建置时间(build times)
二十六、条款26-尽可能延后变量定义式的出现时间
1.只要你定义了一个变量而其类型带有一个构造函数或析构函数,那么当程序的控制流(control flow)到达这个变量定义式时,你便得承受构造成本;当这个变量离开其作用域时,你便得承受析构成本。即使这个变量最终并未被使用,仍需耗费这些成本,所以你应该尽可能避免这种情形
2.对于for循环,做法一是定义于循环体外,做法二是定义于循环体内。除非(1)你知道做法一整体成本比做法二整体成本低,(2)你正在处理代码中效率高度敏感的部分,否则你应该使用做法二。做法一的变量名作用域比做法二大,有时那对程序的可理解性和易维护性造成冲突
3.尽可能延后变量定义式的出现。这样做可增加程序的清晰度并改善程序效率
二十七、条款27-尽量少用转型动作
1.旧式转型仍然合法,但新式转型较受欢迎。原因是:第一,它们很容易被辨识出来,因而得以简化“找出类型系统在哪个地点被破坏”的过程。第二,各转型动作的目标愈窄化,编译器愈可能诊断出错误的运用
2.单一对象(例如一个类型为Derived的对象)可能拥有一个以上的地址(例如“以Base*指向它”时的地址和“以Derived*指向它”时的地址)
3.如果你发现你自己打算转型,那活脱是个警告信号:你可能正将局面发展至错误的方向上。如果你用的是dynamic_cast更是如此
4.除了对一般转型保持机敏与猜疑,更应该在注重效率的代码中对dynamic_cast保持机敏与猜疑(dynamic_cast的许多实现版本执行速度相当慢)
5.如果可以,尽量避免转型,特别是在注重效率的代码中避免dynamic_casts。如果有个设计需要转型动作,试着发展无需转型的替代设计
6.如果转型是必要的,试着将它隐藏于某个函数背后。客户随后可以调用该函数,而不需要将转型放进他们自己的代码内
7.宁可使用C++-style(新式)转型,不要使用旧式转型
二十八、条款28-避免返回handles指向对象内部成分
1.避免返回handles(包括references、指针、迭代器)指向对象内部。遵守这个条款可增加封装性,帮助const成员函数的行为像个const,并将发生“虚吊号码版”(dangling handles)的可能性降至最低
二十九、条款29-为“异常安全”而努力是值得的
1.有个一般化的设计策略很曲型地会导致强烈保证,很值得熟悉它。这个策略被称为copy and swap。原则很简单:为你打算修改的对象(原件)做出一份副本,然后在那副本身上做一切必要的修改。若有任何修改动作抛出异常,原对象仍保持未改变状态。待所有改变都成功后,再将修改过的那个副本和原对象在一个不抛出异常的操作中置换(swap)
2.当异常抛出时,带有异常安全性的函数会:(1)不泄漏任何资源 (2)不允许数据败坏。这样的函数区分为三种可能的保证:基本型、强烈型、不抛异常型
3.“强烈保证”往往能够以copy-and-swap实现出来,但“强烈保证”并非对所有函数都可实现或具备现实意义
4.函数提供的“异常安全保证”通常最高只等于其所调用之各个函数的“异常安全保证”中的最弱者
三十、条款30-透彻了解inlining的里里外外
1.一个表面上看似inline的函数是否真是inline,取决于你的建置环境,主要取决于编译器。幸运的是大多数编译器提供了一个诊断级别:如果它们无法将你要求的函数inline化(如太过复杂(还有循环或递归)的函数、所有对virtual函数的调用等,inline是编译期行为),会给你一个警告信息(见条款53)
2.将大多数inlining限制在小型、被频繁调用的函数身上。这可使日后的调试过程和二进制升级更容易,也可使潜在的膨胀问题最小化,使程序的速度提升机会最大化
3.不要只因为function templates出现在头文件,就将它们声明为inline
4.不要忘记80-20经验法则:平均而言一个程序往往将80%的执行时间花费在20%的代码上头。这是一个重要的法则,因为它提醒你,作为一个软件开发者,你的目标是找出这可以有效增进程序整体效率的20%代码,然后将它inline或竭尽所能的将它瘦身。但除非你选对目标,否则一切都是虚功
三十一、条款31-将文件间的编译依存关系降至最低
1.“以声明依存性”替换“定义的依存性”,那正是编译依存性最小化的本质:现实中让头文件尽可能自我满足,万一做不到,则让它与其他文件内的声明式(而非定义式)相依。其他每一件事都源自于这个简单的设计策略:
[1]如果使用object references或object pointers可以完成任务,就不要使用objects
[2]如果能够,尽量以class声明式替换class定义式
[3]为声明式和定义式提供不同的头文件
2.支持“编译依存性最小化”的一般构想是:相依于声明式,不要相依于定义式。基于此构想的两个手段是Handle classes和Interface classes
3.在程序开发过程中使用Handle classes和Interface classes以求实现码有所变化时对其客户端带来最小冲击。而当它们导致速度和/或大小差异过于重大以至于classes之间的耦合相形之下不成为关键时,就以具象类(concrete classes)替换Handle classes和Interface classes

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值