Effective C++ 笔记1: 用const和inline代替define
define的使用一般有几种情况:
1. 用来定义常量,如
#define pi 3.1415926
2. 用来定义小函数,如
#define max(a,b) ((a) > (b) ? (a) : (b))
3. 用于
#ifndef _DEBUG
...
#endif
这样的组合
对于第一种情况,可以用const代替;第二种情况可以用inline来代替;第三种情况现在还没有其它方案
用const代替define来定义常量
因为define定义常量只是在编译之前用其值来代替符号(如上面的例子中是用3.1415926代替 pi ),所以如果在编译时出了错误,错误可能比较难发现。因为编译器只看到3.1415926这个数,而看不到 pi 这个符号,所以提示信息里很可能只会告诉你3.1415926这个数出现的地方有错,这时你就得去找3.1415926这个数到底在哪里定义的。
而如果用const float pi=3.1415926来定义就要简单得多了,出错信息会告诉你是 pi 出了错,这就简单多了。
用inline代替define来定义函数
define定义函数的最大缺点就是它只是简单替换,所以函数的参数可能会改变函数的行为。
比如上面定义的max,如果有这么一段代码:
int a = 5, b = 0;
max(++a, b); // a is incremented twice
max(++a, b+10); // a is incremented once
可以看到对两次调用,++a执行的次数是不一样的。而如果用inline,写成如下形式:
inline int max(int a, int b) { return a > b ? a : b; }
就不会有这个问题了。
其它相关问题
在class里定义常量
有时候我们希望常量只在一个类里有效,比如:
template <class T>
class set{
static const int DefaultSize=10;
public:
set(){data=new T[DefaultSize];}
protected:
T * data;
}
按照标准,还应该在实现文件里加一句
const int set::DefaultSize;
但即使不加,这样的语法在VC++.NET里也不会出错。
在一些比较古老的编译器里这样的语法就会出错了,比如在VC++6.0里就不行,它不允许在类的声明文件里初始化 DefaultSize,所以我们只能这么写:
template <class T>
class set{
static const int DefaultSize;
public:
set(){data=new T[DefaultSize];}
protected:
T * data;
}
然后在类的实现文件里写
const int set::DefaultSize=10;
但这里又有个问题,如果我们的代码这么写,就出问题了:
template <class T>
class set{
static const int DefaultSize;
protected:
T data[DefaultSize];
}
在初始化 data 时,DefaultSize 还没被赋值。怎么办呢,只能这么写了:
class GamePlayer {
private:
enum { NUM_TURNS = 5 }; // "the enum hack" — makes
// NUM_TURNS a symbolic name
// for 5
int scores[NUM_TURNS]; // fine
...
};
这个方法很变态,但这也是没办法的办法了。