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

Prefer consts, enums, and inlines to #defines

#define

#define ASPECT_RATIO 1.653

#define不被视为语言的一部分,其后的符号没有在记号表(symbol table)内。由预处理器处理,编译时产生的错误不能很好追踪。
解决之道是以一个常量替换上述的宏:

const double AspectRatio = 1.653

对浮点常量而言,使用常量可能比使用#define产生较小量的码,预处理器“盲目地将宏名称ASPECT_RATIO替换为1.653”,此举可能导致目标码出现多份1.653,若改用常量AspectRatio绝不会出现相同的情况。


class专属常量

class GamePlayer {
private:
    static const int m_NumTurns = 5;    // 常量声明式
    int scores[m_NumTurns];
    static const double m_Factor;       // 常量声明,位于头文件内(.h中)
    ...
};

const int GamePlayer::m_NumTurns;       // 常量定义,位于实现文件内(.cpp中)
const double GamePlayer::m_Factor = 1.35;

上面是NumTurns的声明式而非定义式。所谓的“in-class初值设定”也只允许对 整数常量 进行。有些编译器不允许“static整数型class常量”完成“in class初值设定”,可改用所谓的“the enum hack”补偿做法。其理论基础是:“一个属于枚举类型的数值可充当int类型被使用”,于是上面GamePlayer可定义如下:

class GamePlayer {
private:
    enum { m_NumTurns = 5; }    // the enum hack
    int scores[m_NumTurns];
    ...
};

从某方面说enum hack的行为比较像#define而不像const,有时候这正是你想要的。例如取一个const的地址是合法的,但取一个enum的地址就不合法,而取一个#define的地址也通常也不合法。如果你不想让别人获得一个pointer或reference指向你的某个整数常量,enum可以帮助你实现这个约束。


带参数宏定义的误用

// 以a和b的较大值调用函数f
#define CALL_WITH_MAX(a, b) f((a) > (b) ? (a) : (b))

宏看起来像函数,且不会招致函数调用带来的额外开销。但这般长相的宏有着太多的缺点,纵使你记得为所有实参加上小括号,不信看看下面不可思议的代码:

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

这这里,调用f之前,a的递增次数竟然取决于“它被拿来和谁比较”!
幸运的是我们有template inline函数,不仅有宏的效率还有同一般函数一样的所有可预料行为和类型安全性:

template<typename T>
inline void callWithMax(const T& a, const T& b)
{
    f(a > b ? a : b);
}

总结

  • 对于单纯的常量,最好以const对象或enum替换#define
  • 对于形似函数的宏,最好改用inline函数替换#define
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值