编译器是否足够聪明以检测无操作功能?

时间:2010-06-06 18:50:42

标签: c++

如果我写这样的函数:

void doMaybeNothing()
{ 
#ifndef IM_LAZY
   doSomething();
#endif
}

现代编译器是否足够智能以检测无操作功能并进行优化,以便不会浪费周期?或者是否总会产生很小的性能影响?

4 个答案:

答案 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_opmain的来电。

答案 2 :(得分:1)

如果对doMaybeNothing的调用在同一个源文件中,那么大多数现代编译器都会完全优化它。

如果调用是在一个单独的源文件中,特别是如果它在不同的库中,那么你通常会得到函数调用的小开销 - 但函数会立即返回。

还有一件事:这听起来像是过早的优化。在你描述你的程序之前,不要担心这样的事情。

答案 3 :(得分:0)

除了已经提到的其他答案之外,另外要考虑的另一件事是#ifndef由预处理器处理,它只是文本替换 - 编译器。
除了预处理器吐出的内容之外,编译器永远不会看到任何内容。因此,根据是否定义IM_LAZY,编译器将只看到以下之一:

void MaybeDoNothing()
{
}

void MaybeDoNothing()
{
    doSomething();
}