Effective C++随笔 26 to 31 实现

26.尽可能延后变量定义式的出现时间

这样做不止能增加程序的清晰度,还能略微改善程序效率。变量被过早定义容易被编程者遗忘,若到其作用前抛出一个异常,则该变量未被使用但仍需负担其构造析构代价。因此C++通常使用随用随定义的方式。

这里给出一个应该在循环内外定义变量的讨论:
Effective C++随笔 26 to 31 实现_第1张图片
方法A需要一个构造函数,一个析构函数,n个赋值操作。
方法B需要n个构造函数,n个析构函数。
一般来说方法A比较高效,但其作用域也更大,有可能带来不必要的冲突。因此除非该代码段对效率极度敏感,否则更倾向于使用方法B(具体看情况分析,若需设一初值,此后值随循环变动则应使用方法A;否则使用方法B)。

27.尽量少做转型动作

转型方式:

旧式转型(继承于C)
在这里插入图片描述
新式转型
Effective C++随笔 26 to 31 实现_第2张图片

Effective C++随笔 26 to 31 实现_第3张图片
一般来说,我们更推荐使用新式转型。一来他们在代码中很容易被辨识出来;二来转型的目标越窄,编译器越有可能发现潜在的错误。
令人惊异的是:转型不只是改变了数据的解读方式,整个转型过程需要内部的一系列代码实现。

同时,我们也会遇到隐式的转换
Effective C++随笔 26 to 31 实现_第4张图片
我们给出的一个忠告是:“由于知道对象如何布局”而设计的转型并不总是有效,它常常会随平台或编译器的不同而不同。

应当指出的是,dynamic_cast操作相当慢。
dynamic_cast应用于当我们只有一个基类的指针,而我们又确认它指向一个派生类对象并需要对其完成派生类操作的情况下。此时有两种策略可以避免使用dynamic_cast:
(1)使用容器存储指向派生类的指针,如此消除了使用基类指针处理派生类的需要。
(2)使用虚函数机制定义基类与各派生类应当提供的实现。

28.避免返回handle指向对象内部成分

这里的handle可以指引用、指针、迭代器,一旦我们使用handle指向对象内部成分,该类的封装性就被破坏。尤其是访问级别较低者(private与protected),一旦出现了指向它们的handle,它们的访问级别就提升如同public,这意味着类的设计者想要隐藏的数据与方法全部暴露,用户将可以通过这些handle调用并修改这些数据。

29.为“异常安全”而努力是值得的

异常安全函数提供以下的三个保证之一:
(1)基本承诺:若异常被抛出,程序内的任何事物依然保持在有效状态下,没有任何对象和数据结构会因此被破坏。
(2)强烈保证:若异常被抛出,程序状态不改变,程序恢复到调用函数之前的状态。
(3)不抛出保证:承诺永不抛出异常,因为它们总能完成它们原先承诺的功能。

30.透彻了解inline

调用inline函数时不必负担函数调用时的额外开销。但过度热衷于inline会导致程序体积太大,降低cache的命中率进而影响程序性能。

inline只是一个对编译器的申请,并非强制命令,下面给出了隐式的inline申请:将函数定义在类内,这样的函数通常是成员函数,但此外friend友元函数也是在类内声明,故友元函数也是内联函数。
Effective C++随笔 26 to 31 实现_第5张图片
同样,也可用关键字显式声明。
在这里插入图片描述
template与inline一般都放在头文件中在编译器完成。
我们应当审慎地使用inline,将大多数inline限制在小型、被频繁调用的函数身上,这可使潜在的代码膨胀问题最小化,使程序的速度提升机会最大化。

31.将文件间的编译依存关系降至最低

这一条目可大大降低修改某个类后重新编译所用的时间。
使接口与实现分离的关键是:以“声明的依存性”替代“定义的依存性”。
简单策略:
(1)如果使用引用或指针就能满足要求,就不要使用对象
(2)如果能够,尽量以类的声明式代替类的定义式
(3)为声明式与定义式提供不同的头文件

程序库头文件应该以“完全且仅有声明式”的形式存在,无论是否有template都适用。

你可能感兴趣的:(Effective,C++)