类似宏的函数和奇怪的行为
Function-like macros and strange behavior
本文关键字:函数 更新时间:2023-10-16
我已经开始阅读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
这里,a在调用f之前递增的次数这取决于它与什么相比!
事实上,如果我在f
中使用一个简单的print语句,7会在第一次调用中被打印出来,但我一辈子都不知道为什么。我是不是错过了一些显而易见的东西?
编译器会逐字逐句地用您传入的内容替换宏。所以你最终得到
int a = 5, b = 0;
f((++a) > (b) ? (++a) : (b));
f((++a) > (b+10) ? (++a) : (b+10));
使用g++ -E myprog.cpp
(如果不使用g++
,请将g++
替换为whatever-your-compiler-is
)-它适用于几乎所有编译器,它将在预处理后生成实际的内容。
这是一个很好的例子,说明了为什么不应该使用宏来做函数类型的事情。
如果你使用内联函数,你会得到更多你(可能)期望的东西:
inline void CallWithMax(int a, int b)
{
f((a) > (b) ? (a) : (b));
}
任何一个优秀的编译器都应该能够做到这一点,至少和宏一样高效,还有一个额外的优势,即在调用代码中对a
和b
求值一次,不会发生任何"奇怪"的事情。
如果使用调试符号构建代码,您也可以逐步执行内联函数,因此,如果您想查看函数中a
和b
的实际值,可以这样做。宏,因为它们扩展到源代码中的原始位置,所以你无法真正看到里面发生了什么。
相关文章:
- "error: no matching function for call to"构造函数错误
- 什么时候调用组成单元对象的析构函数
- 继承函数的重载解析
- 为什么随机数生成器不在void函数中随机化数字,而在main函数中随机化
- C++模板来检查友元函数的存在
- 递归函数计算序列中的平方和(并输出过程)
- 对RValue对象调用的LValue ref限定成员函数
- C++17复制构造函数,在std::unordereded_map上进行深度复制
- 将数组作为参数传递给函数安全吗?作为第三方职能部门,可以探索他们想要的之外的其他元素
- 在C++STL中是否有Polyval(Matlab函数)等价物?
- 为什么使用 "this" 指针调用派生成员函数?
- 将对象数组的引用传递给函数
- 函数调用中参数的顺序重要吗
- 函数向量_指针有不同的原型,我可以构建一个吗
- 使用不带参数的函数访问结构元素
- 代码在main()中运行,但在函数中出现错误
- 内置函数可查看CPP中的成员变量
- 如何获取std::result_of函数的返回类型
- 如何在c++中为模板函数实例创建快捷方式
- 如果C++类在类方法中具有动态分配,但没有构造函数/析构函数或任何非静态成员,那么它仍然是POD类型吗