如果我写这样的函数:
void doMaybeNothing()
{
#ifndef IM_LAZY
doSomething();
#endif
}
现代编译器是否足够智能以检测无操作功能并进行优化,以便不会浪费周期?或者是否总会产生很小的性能影响?
答案 0 :(得分:6)
假设函数的主体在编译时或链接时可用(即,它不在动态链接库中),大多数现代编译器应该去掉对什么都不做的函数的调用(如果启用了优化,当然)。
实际上,这只是内联扩展的一种形式,只要结果相同,它就允许函数体扩展到调用的任何地方。如果函数什么都不做,那么只要内联它就会扩展为空。
答案 1 :(得分:4)
这样的简单函数将被内联并删除。
对于gcc,输入如
#include <stdio.h>
void no_op () {}
int main () {
no_op();
no_op();
no_op();
no_op();
no_op();
no_op();
no_op();
no_op();
no_op();
no_op();
no_op();
no_op();
return 0;
}
结果(-O1
)是
.section __TEXT,__text,regular
.section __TEXT,__textcoal_nt,coalesced
.section __TEXT,__const_coal,coalesced
.section __TEXT,__picsymbolstub4,symbol_stubs,none,16
.text
.align 2
.globl _no_op
_no_op:
@ args = 0, pretend = 0, frame = 0
@ frame_needed = 0, uses_anonymous_args = 0
@ link register save eliminated.
@ lr needed for prologue
bx lr
.align 2
.globl _main
_main:
@ args = 0, pretend = 0, frame = 0
@ frame_needed = 0, uses_anonymous_args = 0
@ link register save eliminated.
@ lr needed for prologue
mov r0, #0
bx lr
.subsections_via_symbols
请注意,不会生成no_op
中main
的来电。
答案 2 :(得分:1)
如果对doMaybeNothing的调用在同一个源文件中,那么大多数现代编译器都会完全优化它。
如果调用是在一个单独的源文件中,特别是如果它在不同的库中,那么你通常会得到函数调用的小开销 - 但函数会立即返回。
还有一件事:这听起来像是过早的优化。在你描述你的程序之前,不要担心这样的事情。
答案 3 :(得分:0)
除了已经提到的其他答案之外,另外要考虑的另一件事是#ifndef
由预处理器处理,它只是文本替换 - 不编译器。
除了预处理器吐出的内容之外,编译器永远不会看到任何内容。因此,根据是否定义IM_LAZY
,编译器将只看到以下之一:
void MaybeDoNothing()
{
}
或
void MaybeDoNothing()
{
doSomething();
}