代码之家  ›  专栏  ›  技术社区  ›  Thijs Koerselman

编译器是否足够智能以检测无操作函数?

c++
  •  3
  • Thijs Koerselman  · 技术社区  · 14 年前

    如果我写这样的函数:

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

    现代编译器是否足够智能,能够检测到无操作函数并进行优化,从而避免浪费周期?还是性能影响总是很小?

    4 回复  |  直到 14 年前
        1
  •  6
  •   James McNellis    14 年前

    假设函数体在编译时或链接时可用(即,它不在动态链接库中),大多数现代编译器应该摆脱对不执行任何操作的函数的调用(当然,如果启用了优化)。

    实际上,这只是内联扩展的一种形式,它允许函数体在调用它的任何地方进行扩展,只要结果相同。如果函数不执行任何操作,那么它只会在内联的任何位置扩展为Nothing。

        2
  •  4
  •   kennytm    14 年前

    这样的简单函数将被内联并删除。

    对于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 是生成的。

        3
  •  1
  •   dmazzoni    14 年前

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

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

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

        4
  •  0
  •   tzaman    14 年前

    除了已经提到的其他答案外,还有一个需要考虑的问题是 #ifndef 由预处理器处理,它只进行文本替换- 编译器。
    除了预处理器发出的指令,编译器什么也看不到。所以,取决于 IM_LAZY 是否已定义,编译器将只看到以下内容之一:

    void MaybeDoNothing()
    {
    }
    

    void MaybeDoNothing()
    {
        doSomething();
    }