g++无法内联函数

5

有这样的一段代码:

int fun1(){
   return 2 + 3;
}

inline int fun2(){  
   return 4 + 5;
}

int main(){
    int a = fun1();
    int b = fun2();
    return 0;
}

以及相应的汇编代码:

    .file   "prog47.cpp"
    .text
.globl _Z4fun1v
    .type   _Z4fun1v, @function
_Z4fun1v:
.LFB0:
    .cfi_startproc
    .cfi_personality 0x0,__gxx_personality_v0
    pushl   %ebp
    .cfi_def_cfa_offset 8
    movl    %esp, %ebp
    .cfi_offset 5, -8
    .cfi_def_cfa_register 5
    movl    $5, %eax
    popl    %ebp
    ret
    .cfi_endproc
.LFE0:
    .size   _Z4fun1v, .-_Z4fun1v
    .section    .text._Z4fun2v,"axG",@progbits,_Z4fun2v,comdat
    .weak   _Z4fun2v
    .type   _Z4fun2v, @function
_Z4fun2v:
.LFB1:
    .cfi_startproc
    .cfi_personality 0x0,__gxx_personality_v0
    pushl   %ebp
    .cfi_def_cfa_offset 8
    movl    %esp, %ebp
    .cfi_offset 5, -8
    .cfi_def_cfa_register 5
    movl    $9, %eax
    popl    %ebp
    ret
    .cfi_endproc
.LFE1:
    .size   _Z4fun2v, .-_Z4fun2v
    .text
.globl main
    .type   main, @function
main:
.LFB2:
    .cfi_startproc
    .cfi_personality 0x0,__gxx_personality_v0
    pushl   %ebp
    .cfi_def_cfa_offset 8
    movl    %esp, %ebp
    .cfi_offset 5, -8
    .cfi_def_cfa_register 5
    andl    $-16, %esp
    subl    $16, %esp
    call    _Z4fun1v
    movl    %eax, 12(%esp)
    call    _Z4fun2v        # why fun2 is called?
    movl    %eax, 8(%esp)
    movl    $0, %eax
    leave
    ret
    .cfi_endproc
.LFE2:
    .size   main, .-main
    .section    .note.GNU-stack,"",@progbits

为什么函数fun2不像普通函数一样内联调用?我读过内联关键字只是编译器的提示,它不必内联函数,但fun2的定义非常简单,所以它可以内联。如何强制g ++内联函数?


你确定需要将函数设置为内联吗?还是这只是出于兴趣而提出的问题? - marnir
5
所有的代码都应该被简化掉,因为它没有任何有用的副作用。别忘了启用优化器。 - Hans Passant
1
打开一些优化并将内联函数声明为静态的是一个不错的开始。 - cyco130
注意函数内联仅在-O3模式下激活。http://www.linuxjournal.com/files/linuxjournal.com/linuxjournal/articles/072/7269/7269t1.jpg - log0
@cyco130,好主意。是否应该始终使用“static inline T f(...)”,它会改变哪些内容被内联或不被内联? - denis
3个回答

14

打开优化选项。使用 -O2(x86_64)对于 main 函数,您将得到以下结果:

0000000000400560 <main>:
  400560:   31 c0                   xor    %eax,%eax
  400562:   c3                      retq   

它不仅是内联的,还被移除了。

如果没有优化,编译器很少会进行内联。(内联使代码更难调试,因此使用默认的非优化选项只进行适度级别的内联是一个好主意。)


7

GCC有一个特性可以强制进行内联:always_inline

inline int fun2()  __attribute__((always_inline));
inline int fun2() {  
   return 4 + 5;
}

这将使其在任何优化设置下都能正常运行。


5
我会尽力做到最好。需要翻译的内容如下:我认为从不强制编译器进行内联。当决定内联时,编译器比人类更擅长此项工作。一个更简单的想法就是打开进行内联的优化选项。 - Martin York
1
我也建议永远不要强制编译器进行内联。但我不认为编译器总是比人类做得更好。有时候人类会胜出,而那种能够胜出的人也知道何时可以忽略这个建议。对于我们其他人来说,相信编译器就好了 :) - ObscureRobot
@LokiAstari 有一些情况需要强制使用inline。它在调试时非常有用,还可以用于别名函数。与宏相同的功能,但是类型安全。 - Pubby
1
@ObscureRobot: 不幸的是,人类分为三种类型:1)知道自己对编译器一无所知的人。2)认为自己懂编译器的人。3)了解编译器却知道自己还有很多不懂的人。非程序员属于第一类,而大多数程序员属于第二类。 - Martin York
据我所知,“always_inline”中的“always”是指编译器的优化级别。也就是说,即使关闭了优化,该函数也会被内联。 - Shalom Craimer

5

inline是一个编译器提示。编译器可能会或者不会实际地将您的代码内联。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接