页面装载中...

Effective C++ 学习笔记(一):不滥用 #define 宏

从图书馆借到 Scott Meyers 先生著、侯捷先生译的《Effective C++ 中文版(第二版)》后就爱不释手了,大有相见恨晚的感觉。——这样的好书还是应该自己买一本作为居家旅行必备,最新的是第三版,相比第二版改动较大,如果钱包允许,建议每版各买一本,我不是开玩笑滴。XD

想来 blog 长草多日也该清理清理了,顺便把自己学习的一点点体会发上来充数。高手见笑了。

------ 从这里分割 ------

这篇笔记的主要内容来源于《Effective C++ 中文版》第三版的条款 02:尽量以 const, enum, inline 替换 #define。用作者的话来解释,这个条款的意思就是“宁可以编译器替换预处理器”,因为“#define 不被视为语言的一部分”。

#define 来定义常量的部分我就直接略过了,只谈谈用 #define 实现形似函数的宏时出现的问题。可能最常见的一个例子就是实现返回两者中较大者的 max 函数了:

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

撇过这个宏的功能不说,光长相就够不堪的了,在写这种宏的时候,我们必须记得为宏中的每个实参都加一个小括号,不然在调用的时候肯定会碰到不少麻烦。

接下来我们再看看它是不是好用:

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

从上面的例子你能看出一个严重的问题,参数 a 的累加次数居然取决于“它被拿来和谁比较”。

还有一个例子是我之前看到的一个 C++ 面试题目,出处找不着了,题目可能是这样的:

#define SQR(X) X*X

int a = 10, k = 2, m = 1;
a /= SQR(k + m) / SQR(k + m); // 求 a 的值

可能我们会想当然地算一个结果(或许是 10?)出来,那就大错特错了。原因也很简单。#define 宏在编译时只进行替换,而不进行任何运算,上面的式子实际上相当于:

a /= (k + m)*(k + m)/(k + m)*(k + m);

再算算,结果一定跟你之前想的不一样。晓得 #define 有多坏了吧,呵呵。

有人会说,宏的好处是不会产生函数调用的开销。这个不是问题,inline 关键字可以帮你实现同样的性能,一样不会产生函数调用的额外开销。

先写这么多了,写不好,大家将就看。

上一篇:过年回来了
下一篇:要搬家了

0排都被占了... 抢座 或 Trackback

我要占座!

Connecting to server...