Effective C++ define 定义的名字, 不在记号表中(预处理器处理过之后, 就是替换后的值了) define 不重视作用域, 没有类型安全

第二遍读EC++, 虽然对于大部分一看便知, 但是每个条目的内容总是想不出来. 这里记录一下, 希望这些key point能够帮助读这本书的朋友瞬间想起来条目内容

个人不太习惯侯捷先生的翻译, 下面是笔者自己的理解.

Item 01: View C++ as a federation of languages

(把C++看成是一个语言联盟)

  1. C++支持多范式编程: 面向过程, 基于对象, 面向对象, 范型设计(模板)及TMP(template metaprogramming)

Item 02: Prefer consts, enums, and inlines to #defines

(优先使用 consts, enums, inlines, 而非 #define)

  1. define 不重视作用域, 没有类型安全

  2. 类中的 enum hack 补偿行为理论基础: 一个属于枚举类型的数值可以被当成 ints 使用. TMP中大量使用这种作法
    C++11中加入了 constexpr 可以替换这种使用方法. (在 《C++ Template》书中,提到也有一种情况替换不了)
  3. 宏定义出的仿函数,调用时要严防副作用。
    int a = 5, b = 0;
    CALL_WITH_MAX(++a, b); // a 被累加二次
    CALL_WITH_MAX(++a, b + 10); // a 会被累加一次
  4. 目前对于宏, 还不能完全消除. (例如 头文件中使用的 #ifndef ... #define.. #endif)

Item 03: Use const whenever possible

(只要可能, 就使用const)

  1. 可帮助编译器检测错误, 还有利用优化.
  2. class Rational {...};
    const Rational operator* (const Rational & lhs, const Rational & rhs);
    此处返回值带const, 可以避免这种错误:
    if (a * b = c) ... // 此处如果想使用比较的话
    (一个良好的用户自定义类型的特征是它们避免无端地与内置类型不兼容)
  3. 两个成员函数如果只是常量值不同, 可以形成重载.
  4. 两个成员函数, 如果只是常量性不同, 可以使用其中一个调用另一个, 但:
    必须是non-const 调用 const成员函数, 其中要有两次转型(一次是对 *this 转换, 一个是对调用的返回结果)

Item 04: Make sure that objects are initialized before they're used.

(确保对象使用前都已被初始化)

  1. 最好的方便是: 使用前先初始化
    1. 对于无任何成员的基本类型, 你需要手动完成
    2. 对于ADT, 这是ctor的责任(1. 注意与声明顺序相同, 2. 不要在ctor函数体内使用赋值操作)
  2. 为免除"跨编译单元的初始化顺序"问题, 请用local static对象替换non-local static对象(把对象放到函数中, 返回之)

Item 05: Know what functions C++ silently writes and calls

(了解C++静默为你实现并调用的函数)

  1. default ctor, dtor, copy ctor, copy assignment

Item 06: Explicitly disallow the use of compiler-generated function you do not want

(显式拒绝(阻止)你不想让编译器为你生成的那些函数)