空内联函数究竟会发生什么
What exactly happens to empty inline functions?
我正在编写代码(使用GCC 4.7.2),在测试阶段,我在代码的无数位置过度记录内容。这些日志应该在发布二进制文件中消失。
我通过一个类似void log(std::string msg);
的函数进行日志记录。由于这些函数调用是多个的,并且通过许多文件中的整个代码进行分布,所以我想将其作为一个内联函数,并为发布二进制文件提供一个空的主体。
不,我的问题是:编译器用它做什么?二进制文件是否只包含没有函数的代码的其余部分,是否包含nop
或其他内容?我可以通过清空内联日志记录函数来完全消除二进制文件中的日志记录代码吗?
我不仅对解决问题的答案感兴趣,而且对编译器的行为本身也很好奇。
如果您希望在调试和发布之间使用不同的代码,那么这是预处理器的理想用例:
#ifdef NDEBUG
#define log(ignored)
#endif
那么你就不会把任何东西留给编译器了。您可以保证只有调试版本才会有额外的调用。assert
也是这样工作的。
请注意,这也将放弃参数计算。例如,如果您有log(get_msg())
,那么宏方法也会放弃对get_msg()
的调用。这可能是可取的,但你需要意识到这一点
至于inline
,这完全取决于编译器。inline
关键字本身只是一个提示,它并不要求编译器做任何事情。编译器对是否内联特定函数(包括未标记为inline
的内联函数)执行自己的优化计算。这通常意味着一个足够高的优化级别(即-O3),并且内联函数的主体在特定的编译单元中是可见的。例如,如果编译器只看到一个声明,但(可能是空的)函数体在另一个.cpp文件中,则它不能内联。但是是的,如果编译器确定没有副作用,那么可以自由地使整个函数消失。
但是,当预处理器提供如此干净和广泛使用的解决方案时,没有理由依赖它。
您可能会也可能不会留下一个平凡的空函数(例如,如果函数的地址用于创建指针,则该函数需要存在)。
但是,所有内联调用站点都将变为空。(编译器应该选择始终内联直接调用一个它可以看到是空的函数——Adam的答案是正确的,即调用其他翻译单元会使这变得困难,但整个程序优化甚至可以在那里提供帮助)
但是,请注意,内联函数的参数仍将被求值。它们也可能被内联并大部分被消除,但参数中的副作用将发生。这与使用#define
宏从源代码中删除整个log(...)
字符串大不相同。宏也去掉了参数计算。
- 传递给std::function template的template参数究竟代表什么
- C++关于指针和使用函数将它们启动到堆的行为究竟是什么?
- 当使用对象名称后带有 [] 的类对象时,您究竟会传入什么.C++
- 哪种方式更快?究竟发生了什么,我们没有看到什么?
- 当我使用 void 函数的返回值(通过强制转换函数指针)时,究竟会发生什么?
- DrawShadow 中的 Elevation 究竟有什么作用?
- 究竟是什么设置了_WIN32或_WIN64预处理器?
- GCC 的 -Wpsabi 选项究竟有什么作用?压制它意味着什么?
- 这个编译器错误究竟希望我执行什么?
- 在陈述"Implementation-defined"时,什么样的软件是"Implementation"的一部分?究竟什么是"Implementation"?
- 究竟什么是"位填充"或"填充位"?
- 究竟发生了什么,我们需要在 c++ 中双重调度/访客
- 根据标准,究竟什么是"declaration of an object"
- wchar_t究竟能代表什么
- 此模板中究竟检查了什么?
- a = !5 < a;在这一行代码中究竟做了什么?
- 绑定 API 在服务器程序中究竟做了什么
- 这个给定算法中的"basic operation"究竟是什么
- GetModuleFilenameEx返回0,getlasterror返回溢出错误.我究竟做错了什么
- 为了对象替换的目的,究竟什么构成了对象的"name"?