1.尽可能延后变量定义式的出现时间
应该延后变量的定义,直到能够给它初值为止.这样不仅能够避免构造(和析构)非必要对象,还可以避免无意义的default构造行为
方法A:一个构造函数 + 1个析构函数 + n个赋值操作
Widget w; for (int i = 0; i < n; ++i) { w = value; //... }
方法B:n个构造函数 + n个析构函数
for (int i = 0; i < n; ++i) { Widget w(value); //... }
通常采用方法B,方法A中w的作用域比做法B大
2.尽量少做转型动作
const_cast通常用来将对象的常量性移除,它是唯一有此能力的c++-style转型操作符
dynamic_cast主要用来执行安全向下转型,比如将指向基类的指针或引用类型转换为指向派生类的指针或引用,dynamic_cast的许多实现版本执行速度相当慢,在注重效率的代码中要尽量避免dynamic_cast
static_cast用来强迫隐式转换,比如将non-const对象转为const对象,但它无法将const转为non-const
class Window { public: Window() { width = 2; height = 2; } virtual void onResize() { width = 10; } int width; int height; }; class SpecialWindow :public Window { public: virtual void onResize() { /* 在当前对象的base class成分的副本上调用Window::onResize,然后在当前对象身上执行SpecialWindow专属动作。如果Window::onResize 修改了对象内容,当前对象没被改动,改动的是副本,然后SpecialWindow::onResize内如果也修改对象,当前对象会被改动 */ //若只是想在派生类中调用基类版本的onResize函数,用下面的代码 //Window::onResize(); static_cast<Window>(*this).onResize(); height = 3; } }; int main() { SpecialWindow sw; sw.onResize(); cout << sw.width << " " << sw.height << endl;//输出2 3 system("pause"); return 0; }
3.避免返回handles(reference、指针、迭代器)指向对象内部成分
遵守这个条款可增加封装性,防止handles指向不存在的对象
4.为"异常安全"而努力
异常安全函数提供以下三个保证之一:
基本承诺:如果异常被抛出,程序内的任何事物仍然保持在有效状态下,但具体哪个状态不可预料
强烈保证:如果异常被抛出,程序会回复到调用函数之前的状态,能够通过copy-and-swap实现,但强烈保证并非对所有函数都可实现或具备现实意义
不抛掷(nothrow)保证:承诺绝不抛出异常,因为它们总是能够完成它们原先承诺的功能。作用于内置类型(如int,指针等)身上的所有操作都提供nothrow保证.
5.透彻了解inlining的里里外外
inline函数背后的整体思想是,将对此函数的每一个调用都以函数本体替换,免除函数调用成本,但过度热衷inlining会造成程序体积太大
inline只是对编译器的一个申请,不是强制命令。这项申请可以隐式提出,也可以明确提出。隐式方式是将函数定义于class定义式内(包括成员函数和友元函数)。
inline函数无法随着程序库的升级而升级,如果f是程序库内的一个inline函数,客户将f函数本体编进其程序中,一旦程序库设计者决定改变f,所有用到f的客户端程序都必须重新编译。而如果f是non-inline函数,一旦它有任何修改,客户端只需要重新连接就好,远比重新编译的负担少很多。
大部分编译器拒绝将太过复杂(带有循环或递归)的函数inlining,而所有对virtual函数的调用都会使inlining落空.virtual意味着等待,直到运行期才确定调用哪个函数,inline意味着执行前,先将调用动作替换为被调用函数的本体
6.将文件间的编译依存关系降至最低
6.1. 如果使用object references或object pointers可以完成任务,就不要使用objects.你可以只靠一个类型声明式就定义出指向该类型的references和pointers;但如果定义某类型的objects,就需要用到该类型的定义式
6.2. 如果能够,尽量以class声明式替换class定义式.当你声明一个函数而它用到某个class时,你并不需要该class的定义,纵使函数以by value方式传递该类型的参数(或返回值)亦然
6.3. 为声明式和定义式提供不同的头文件