Skip to content

Latest commit

 

History

History
107 lines (73 loc) · 3.54 KB

EffectiveC++.md

File metadata and controls

107 lines (73 loc) · 3.54 KB



一.让自己习惯C++

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

这个条款或许改为“宁可以编译器替换预处理器”比较好

1)以const替换#define

#define ASPECT_RATIO 1.653
替换为:
const double AspectRatio = 1.653
  • 处于调试的需要:#define的记号会被预处理器移走,记号名称可能没进入记号表内。因此当#define的宏名称获得一个编译错误时,会引起困惑,浪费大量时间追踪错误。而AspectRatio肯定会被编译器看到
  • 更小的代码量:对浮点数而言,使用常量可能比使用#define导致较小量的代码,因为预处理器“盲目地将ASPECT_RATIO替换为1.653”可能导致目标码出现多份1.653

但是,以常量替换#define时要注意:

  • 定义常量指针时:由于常量定义式通常被定义在头文件内,因此有必要将指针声明为const。如:
    const char* const authorName = "Scott Meyers";
  • class专属常量:class专属常量需要声明在class内部,并且被class使用:
    class GamePlayer{
        static const int NumTurns = 5; //常量声明式
        int scores[NumTurns];          //使用该常量
    };
    //通常定义出现在头文件中
    const int GamePlayer::NumTurns;    //NumTurns的定义
    对于static修饰的class专属整形常量,如果需要对该常量取地址或编译器坚持要看到一个定义式。那么必须提供类外定义。如果类内声明时提供了初始值,类外定义就不能再设初值。但是某些编译器可能不支持类内初始值,因此需要在类外定义时提供初始值,但是这样就没有像scores成员一样,在类内使用该常量。因此,如果需要使用class专属常量,最好改用“enum hack

2)以enum替换#define

正如说明说提到的,编译器可能不支持类内初始值,因此改用"enum hack":

class GamePlayer{
    enum {NumTurns = 5};
    int scores[NumTurns];   //这就没问题了
};

enum hack的行为比较像#define而不像const。例如取一个const的地址时合法的,但取一个enum的地址就不合法,而取一个#define的地址通常也不合法

3)以inline替换#define

以#define实现宏看起来像函数,并且不会导致函数调用带来的开销,但是可能引发错误:

#define CALL_WITH_MAX(a,b) f((a) > (b) ?  (a) : (b))

int a = 5,b = 0;
CALL_WITH_MAX(++a,b);       //a被累加2次
CALL_WITH_MAX(++a,b + 10);  //a被累加1次

使用inline函数可以减轻为参数加上括号以及参数被核算多次等问题。同时,inline可以实现一个“类内的private inline函数”,但一般而言宏无法完成此事


二.构造/析构/赋值运算


三.资源管理


四.设计与声明


五.实现


六.继承与面向对象设计


七.模板与泛型编程


八.定制new和delete


九.杂项讨论