2

我知道我可以将函数指针作为模板参数传递并内联调用它,但我想知道这些天是否有任何编译器可以内联一个“明显”的内联函数,例如:

inline static void Print()
{
 std::cout << "Hello\n";
}

....

void (*func)() = Print;

func();

在 Visual Studio 2008 下,它足够聪明,可以将其归结为直接调用指令,所以它似乎很遗憾不能更进一步?

4

3 回答 3

4

较新版本的 GCC(4.4 及更高版本)有一个名为 -findirect-inlining 的选项。如果 GCC 可以向自己证明函数指针是常量,那么它会直接调用该函数或完全内联该函数。

于 2010-06-02T17:01:37.883 回答
2

GNU 的 g++ 4.5 从优化级别 -O1 开始为我内联它

main:
    subq    $8, %rsp
    movl    $6, %edx
    movl    $.LC0, %esi
    movl    $_ZSt4cout, %edi
    call    _ZSt16__ostream_insertIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_E
    movl    $0, %eax
    addq    $8, %rsp
    ret

其中 .LC0 是 .string "Hello\n"。

为了比较,没有优化,g++ -O0,它没有内联:

main:
    pushq   %rbp
    movq    %rsp, %rbp
    subq    $16, %rsp
    movq    $_ZL5Printv, -8(%rbp)
    movq    -8(%rbp), %rax
    call    *%rax
    movl    $0, %eax
    leave
    ret
于 2010-06-02T17:00:54.797 回答
1

好吧,编译器并不真正知道该变量是否会在某个地方被覆盖(可能在另一个线程中?)所以它会谨慎行事并将其作为函数调用来实现。

我刚刚在发布版本中签入了 VS2010,但它没有被内联。

顺便说一句,您将功能装饰inline为无用。该标准规定,如果您获得了函数的地址,则任何inline提示都将被忽略。

编辑:但是请注意,虽然您的函数没有内联,但变量已消失。在反汇编中call使用直接地址,它不会将变量加载到寄存器中并调用它。

于 2010-06-02T16:24:35.447 回答