【问题标题】:c++ Function pointer inliningc++ 函数指针内联
【发布时间】:2010-06-02 16:18:19
【问题描述】:

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

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

....

void (*func)() = Print;

func();

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

【问题讨论】:

  • 你确定这不是对ostream&lt;&lt;的直接调用指令吗?
  • 请使用编辑器中的101010 按钮格式化您的代码。
  • 是的,我检查了组件。关于我不知道的代码格式,但现在我知道了:)
  • @wb:我不是故意的,如果是这样的话,我很抱歉。 (哦,你需要正确@attribute评论答案,否则当你回答时我们不会收到通知。)
  • @sbi:别担心,我不认为你这样做我只是在澄清:)

标签: c++ function pointers inlining


【解决方案1】:

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

【讨论】:

    【解决方案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
    

    【讨论】:

    • 很高兴知道有各种有用的结构,这将使它们的使用对性能产生零影响:) 可惜 Visual C++ 还没有那么聪明!谢谢。
    【解决方案3】:

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

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

    顺便说一句,你把函数装饰成inline 是没用的。标准规定,如果您获得函数的地址,任何inline 提示都将被忽略。

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

    【讨论】:

    • 是的,我就是这么想的,所以我只是尝试了 __restrict 并且 const 也无济于事。是的,我尝试过 inline 和 __forceinline,因为你永远不知道 :) IE: void (*const __restrict func)() = Local::Print;我希望在 VS2010 中他们可能会因为 lambda 等而拥有它 - __restrict 是否会改变 VS2010 中的情况?谢谢
    • 不,编译器拒绝内联它,这有点奇怪,因为如果它消除了变量,那么变量就不会发生变化的危险,所以它可以将 call 替换为功能体。哦,好吧..
    • 编译器不必假设变量可以在另一个线程中被覆盖。如果同一个线程有可能覆盖变量,编译器必须确保它安全,但在像 OP 所示的简单情况下,也没有风险(这也是它能够消除多变的)。编译器应该能够内联这样的简单案例。
    • 是的,看我的编辑,它确实意识到变量不会被覆盖,所以它只是完全放弃它并对Print函数进行硬编码调用。它应该内联它,但它没有。
    • 如果 MSVC++ 在这种情况下可以做 GCC 可以做的事情,那就太好了。知道它应该能够做到这一点仍然很有用。
    猜你喜欢
    • 2012-02-11
    • 2011-06-19
    • 2016-10-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多