【问题标题】:Is it possible to inline a lambda expression? [duplicate]是否可以内联 lambda 表达式? [复制]
【发布时间】:2011-03-19 13:57:06
【问题描述】:

我想内联一个 lambda 表达式,因为出于性能原因它非常短。有可能吗?

【问题讨论】:

标签: c++ c++11 lambda inline inlining


【解决方案1】:

inline 关键字实际上不会导致函数被内联。任何最近的编译器都会在内联方面做出比你更好的决定。

在短 lambda 的情况下,函数可能会被内联。

如果您尝试将 inline 关键字与 lambda 一起使用,答案是否定的,您不能使用它。

【讨论】:

  • 对于最近的编译器会比给定的人类意志做出更好的内联决策这一说法,很容易想出反例。当我有速度关键代码时,我根本不是 C 大师,用内联提示标记方法通常会产生更快的可执行文件。所要做的就是测量代码。我会建议任何被告知编译器知道更好地设置测试平台的人,在那里他们可以为各种函数计时,无论是否有内联提示,以探索何时可以超越编译器。
  • @jack 当然。但是你需要像 __declspec(forceinline) 或 __declspec(noinline) 这样的东西来做到这一点。如果这样做可以带来任何可衡量的改进,1. 您需要更多 LTO / LTCG,2. 您需要更多 PGO,或 3. 编译器错误。编译器不会做人们声称他们一直在做的所有事情,但内联是他们通常非常擅长的领域之一。
【解决方案2】:

如果可以的话,编译器会内联它。例如,在带有 -O2 的 g++ 4.5 中,

#include <vector>
#include <algorithm>

int main () {
    std::vector<int> a(10);
    for (int i = 0; i < 10; ++ i) a[i] = i;

    asm ("Ltransform_begin: nop; nop; nop; nop; nop; nop; ");
    std::transform(a.begin(), a.end(), a.begin(), [] (int x) { return 2*x; });
    asm ("Lforeach_begin: nop; nop; nop; nop; nop; nop; ");
    std::for_each(a.begin(), a.end(), [] (int x) { printf("%d\n", x); });
    asm ("Lforeach_done: nop; nop; nop; nop; nop; nop; ");

    return 0;
}

生成 2*xprintf lambda 完全内联的程序集。

# 9 "x.cpp" 1
    Ltransform_begin: nop; nop; nop; nop; nop; nop; 
# 0 "" 2
    .align 4,0x90
L13:
    sall    (%rax)
    addq    $4, %rax
    cmpq    %rax, %r12
    jne L13
# 13 "x.cpp" 1
    Lforeach_begin: nop; nop; nop; nop; nop; nop; 
# 0 "" 2
    .align 4,0x90
L14:
    movl    (%rbx), %esi
    leaq    LC0(%rip), %rdi
    xorl    %eax, %eax
LEHB1:
    call    _printf
LEHE1:
    addq    $4, %rbx
    cmpq    %r12, %rbx
    jne L14
# 17 "x.cpp" 1
    Lforeach_done: nop; nop; nop; nop; nop; nop; 
# 0 "" 2

【讨论】:

    【解决方案3】:

    lambda 表达式可能是内联的。在底层,lambda 表达式与任何其他函数对象没有什么不同。

    一个特定的 lambda 表达式是否被内联完全取决于编译器以及它是否决定它是否值得内联。

    【讨论】:

      【解决方案4】:

      如果你有一个常规的结构函子,编译器几乎肯定会内联它。如果你有一个 C++0x 风格的 lambda,编译器几乎肯定会内联它。如果您使用的是 boost::lambda,那么它可能会这样做,具体取决于 lambda 在场景下的工作方式。短版:你不能保证它是内联的还是非内联的,但你应该相信你的编译器,如果有疑问,让内联变得容易和简单。

      【讨论】:

        【解决方案5】:

        我还没有以任何方式查看其中 很多 个输出,但到目前为止,我查看的所有输出都已被内联。

        【讨论】:

          【解决方案6】:

          C++1x' lambdas 将在底层生成普通函数对象。这些可以由编译器内联。

          您所做的任何测量是否表明编译器没有将它们内联到导致显着性能损失的地方?

          【讨论】:

          • Nitpick:关于 C++1x 的工作还没有开始,这只不过是有根据的猜测,甚至会出现 C++1x。委员会仍在研究 C++0x,工作名称不太可能更改,只是因为它与标准的最终短名称不匹配。
          • @Christopher:我不同意。下一个 C++ 标准很可能是 C++11,可能会变成 C++12,不太可能变成 C++10,也不可能变成 C++09。由于最后一个(并且只有最后一个)数字是不确定的,它通常被替换为x。当然不能保证它是否会有 lambdas(只看概念),但委员会非常不太可能满足于更少的东西。
          • 开玩笑的是 0x 现在是十六进制,因为大多数人继续使用 C++0x
          猜你喜欢
          • 2017-04-19
          • 2014-09-12
          • 2010-11-02
          • 2011-12-05
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多