【Effective C++系列】条款02:尽量以 const, enum, inline 替换 #define

先上总结:

  • 对于单纯变量,最好以const对象或enum替换#define
  • 对于形似函数的宏(macro),最好改用inline函数替换#define

现在我们来看看为什么会有如此总结。


1、为什么最好用const替换#define


利用#define定义宏常量的方式如下:

#define ASPECT_RATIO 1.653

对于宏ASPECT_RATIO有可能并未进入记号表内,编译器并未开始处理就被预处理器移走。如果此变量出现编译错误,错误信息可能只提到1.653, 而不是ASPECT_RATIO,如果它并不在自己定义的头文件中,这会让你很难定位追踪到它,从而浪费时间。

对于这种情况,可以使用const替换#define

const double AspectRatio = 1.653

const修饰的变量作为一个语言常量,肯定会进入记号表。且不会出现#define导致目标码多出一份1.653的问题。

symbol table (记号表)翻译成**“符号表”**应该好理解一些。针对计算机语言,在不同的地方,它的用处也不一样。有词法分析时分词用的符号表,用来把所有用到的标识符区分出来。也有做语法分析时用的语法元素的符号表。编译成目标文件时,也会产生用于内/外部符号定位/链接用的符号表。生成可执行文件时也有类似的符号表…不论在什么地方,符号表的基本都可以看成一个名称索引表,为了方便数据归类查找用的。参考:C++记号表是什么?-CSDN社区

关于使用const常量关键字替#define有两种特别情况需要交代:

1、定义一个指向常量的常量指针时,我们需要写两次const

const char* const authorName = "Mai Bai De Da Di Zhu!"

此时我们可以使用std::string进行替代:

const std::string authorName("Mai Bai De Da Di Zhu!")

2、对于类内部的静态常量静态成员变量,如:

class GamePlayer {
    private:
    	static const int NumTurns = 5;
    	int scores[NumTurns];
    	...
}

通常情况下,类的静态成员不应该在内部进行初始化的,但是我们可以为静态成员提供const整数类型的类内初始值(要求静态成员必须时字面常量表达式constexpr,并且初始值也得是常量表达式。)

不过此时,

static const int NumTurns = 5;

只是NumTurns的声明式,而不是定义式,通常我们也需要在类的外部定义一下NumTurns不过注意:如果我们在类的内部提供了初始值,在外部定义时就不能再指定别一个初始值了(如果编译器不支持在静态成员声明时初始化,则可以将初始化放在定义时)。


2、为什么最好用enum替换#define


对于enum,其数值可充当int整型。enum在某些方面挺像#define而非const,例如你无法取其地址,就像#define一样,而对于const则可以。另外如果你不想别人使用指针或者引用指向你的某个整数常量,你就可以使用enumenum还有具有实用主义的特征,其应用很广泛。


3、为什么最好用inline替换#define


对于宏函数,其繁琐难懂的表达让人看了很烦,如:

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

尤其是要注意其函数定义中的参数,所有实参必须要加上小括号,并且每层计算逻辑都需要加小括号,就算如此,也很可能出现纰漏。

inline(内联)函数的出现可使你很好解决这个问题:

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

另外,无法利用#define创建类的专属成员,无法提供任何封装性。因为#define并不注重作用域,其一旦被定义,在其后的编译过程中就有效(除非在某处被#undef)。而我们可利用inline可定义类内的私有inline函数。


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

卖报的大地主

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值