3

我已经开始阅读 Effective C++ 并且在第 2 项中的某个时间点,提到了以下内容:

// call f with the maximum of a and b
#define CALL_WITH_MAX(a, b) f((a) > (b) ? (a) : (b))

...

int a = 5, b = 0;
CALL_WITH_MAX(++a, b); // a is incremented twice
CALL_WITH_MAX(++a, b+10); // a is incremented once

在这里,在调用 f 之前 a 增加的次数取决于与之比较的对象!

确实,如果我在 中使用简单的打印语句f,第一次调用会打印 7 ,但我终其一生都无法弄清楚原因。我错过了一些明显的东西吗?

4

2 回答 2

5

编译器会用您传入的内容逐字逐句替换宏。所以你最终得到

int a = 5, b = 0;
f((++a) > (b) ? (++a) : (b));
f((++a) > (b+10) ? (++a) : (b+10));
于 2013-02-22T23:12:58.247 回答
1

使用(如果您不使用,请g++ -E myprog.cpp替换g++为) - 它适用于几乎所有编译器,它会在预处理后生成实际的东西。whatever-your-compiler-isg++

这是一个很好的例子,说明了为什么你不应该使用宏来做函数类型的东西。

如果您要使用内联函数,您将获得更多(可能)期望的结果:

 inline void CallWithMax(int a, int b) 
 {
     f((a) > (b) ? (a) : (b));
 }

任何体面的编译器都应该能够至少像宏一样高效地执行此操作,并具有额外的优势,即您的ab在调用代码中被评估一次,并且不会发生任何“奇怪”的事情。

如果您使用调试符号构建代码,您也可以单步执行内联函数,因此如果您想查看函数内部的值ab实际值,您可以这样做。宏,因为它们扩展到源代码中的原始位置,所以你无法真正看到里面发生了什么。

于 2013-02-22T23:20:43.430 回答