内容从侯捷译版的《Effective C++》(第三版)摘录
条款一
C++作为一个多种范式融合的语言,可以看成是语言的联邦,它包含了一下四种主要的次语言:
- C。C++以C为基础,很多时候C++对于问题的解法其实不过就是较高级的C解法,但是C语言的局限:没有模板,没有异常处理,没有重载。
- OO C++。包括类,封装,继承,多态,动态绑定。
- Template C++。 这是C++范型的部分。
- STL。包括三个主要部分。容器(containers),迭代器(iterator),算法(algorithm)。
高效编程守则视状况而变化,取决于你使用C++的哪一部分。
条款二 尽量以 const, enum, inline替换#define
原因在于,#define RATIO 1.6, 中被替换的记号名称RATIO可能从来都没有出现在symbol table中,这样给debug带来很多困难。
使用const代替#define作为常量时,需要注意对于字符串的使用,即“从右往左读规则”:
const char* const authorName = "Meyers"
常量的指针变量authorName指向常量的char(s)。
另外,#define不具备封装性,比如作为class的专属常量:
class GamePlayer{ private: static const int NumTurns = 5; int scores[NumTurns]; ... };
然而以上的申明式不会通过某些编译器,所以需要加入一个定义式:
class GamePlayer{ private: static const int NumTurns; int scores[NumTurns]; ... }; const int GamePlayer::NumTurns = 5;
还有一种使用"enum hack"补偿做法,利用了emun的特点来代替常量,来限制不可取地址的常量成员变量:
class GamePlayer{ private: enum{NumTurns = 5}; int scores[NumTurns]; ... };
使用#define定义函数的缺点太多,例如:
#define CALL_WITH_MAX(a,b) f( (a) > (b) ? (a) : (b) ) int a = 5, b = 0; CALL_WITH_MAX(++a,b); // a被累加二次 CALL_WITH_MAX(++a,b + 10); // a被累加一次 而使用template,代替#define就不需要担心这样的不同: template<typename T> inline void callWithMax(const T& a, const T& b) { f(a > b ? a : b); }
- 对于单纯的常量最好以const对象或者enum代替#define
- 对于宏函数,最好用inline函数替换#define函数
条款三 尽可能使用const
- 将某些东西声明为const可帮助编译器侦测出错误用法。
- 编译器强制使用bitwise constness。bitwise constness指常量成员函数不能改变任何成员变量。Logical constness指的是如果在常量成员函数中或者返回值上又想改变成员变量的值,这个时候可以通过mutable或者const_cast将类的const特性去掉。
- 在有着实质等价实现的时候,non-const成员函数调用const成员函数可以避免代码重复。
条款四 确定对象被使用前已经被初始化
- 手动为内置型对象初始化,C++不保证初始化他们。
- 构造函数最好使用成员初值列(member initialization list)。
- 为避免跨编译单元初始化次序的问题,以local static对象替换non-local static对象