就学习难度而言,C++是一门臭名昭著的编程语言。《Effective C++》总结了 55 条 C++(98/03)的开发准则,供开发者学习参考。本篇笔记包含 Term 01~04,我也依据 Modern C++ 的改变,对其中某些细节进行了修订。

Term 01:视 C++ 为一个语言联邦

这一点说起来容易(做起来难)。简单讲,C++ 的语言设计其实有四个部分 :(兼容)C、面向对象、泛型和模板、STL,这四个部分相互关联却又在设计思想上相对独立。每一个部分都会有一些不同的准则,在 C 中的常用思路不一定适合在泛型和模板中使用。

一般来说,泛型和模板这一部分是 C++ 程序员最薄弱的,需要特别注意。

Term 02:尽量以 const, enum, inline 替换 #define

  1. 对于常量,使用 const 或者 enum hack 代替
  2. 对于形似函数的宏定义,使用 inline 函数代替(可能会用到模板)
// enum hack 的例子:
class Game {
    private:
        static const int GameTurn = 10;
        int scores[GameTurn];
};    //不支持类内初始化的编译器报错
class GamePlayer{
    private:
        enum {NumTurns = 5};
        int scores[NumTurns];
};    //不支持类内初始化的编译器也能编译通过

Term 03:尽可能使用 const

  1. const 和指针:记住 const 出现在 * 左边,表示被指物是常量;如果出现在 * 右边,表示指针自身是常量;如果出现在 * 两边,表示被指物和指针都是常量
  2. STL 的迭代器可以视为指针,const std::vector<int>::iterator iter 效果等同于 T* conststd::vector<int>::const_iterator cIter 效果等同于 const T*
  3. 设置函数返回对象为 const 可以排除一些不必要的安全隐患
  4. 类的成员函数可以通过(函数名之后,函数体之前的那个) const 重载,分别针对 const/non-const 对象
  5. bitwise const 和 logical const 的区别,通过 mutable 实现 logical const
  6. 当成员函数的 const/non-const 版本有同样的实现时,可以将实现代码写在 const 版本中,而在 non-const 版本中调用即可,但是需要注意转换类型,并且一定要小心,避免安全隐患。
class TextBlock {
 public:
  const char& operator[](std::size_t position) const { return text[position]; }
  char& operator[](std::size_t position) {
    return const_cast<char&>(static_cast<const TextBlock&>(*this)[position]);
  }
  // ......
};

Term 04:确定对象被使用前已被初始化

  1. 手动初始化内置型对象,比如 int i = 0;
  2. 构造函数使用成员初值表进行初始化
  3. 为免除“跨编译单元初始化顺序不确定”问题,使用 local static 对象替换 static 对象