自执行 C++11 lambdas 的成本

Rod*_*igo 5 c++ lambda switch-statement c++11 self-executing-function

窗口过程之外,我正在switch使用自执行 lambda编写语句,如下所示:

LRESULT 回调过程(HWND hWnd、UINT msg、WPARAM wp、LPARAM lp)
{
    开关(味精)
    {
        case WM_CREATE: return [&](WPARAM wp, LPARAM lp) {
            do_something(wp, lp);
            返回0;
        }(wp, lp);

        case WM_SIZE: return [&](HWND hWnd) {
            do_another_thing(hWnd);
            返回0;
        }(hWnd);
    }
    返回 DefWindowProc(hWnd, msg, wp, lp);
}

我相信编译器可以按照他们想要的方式自由地优化它,但一般来说,与不使用这些 lambdas 相比,编译器会为此添加很多样板代码吗?

编译器能否检测到多余的 lambdas 并删除它们?

Nir*_*man 6

像这样的优化问题没有明确的答案,因为兼容编译器的优化器可以做很多很多事情。但是,在这种情况下,大多数现代优化器几乎肯定会内联 lambda,并生成相同的程序集,无论您是否使用 lambda。由于 lambda 具有唯一类型,因此编译器可以轻松内联。因为 lambda 被声明并立即使用并且从不分配(更常见的名称是“立即调用/评估的 lambda 而不是“自执行”),编译器知道它只能被调用一次。所以通常它会决定内联。

可以肯定的是,您可以查看一些程序集:https : //godbolt.org/g/QF6WmR。如您所见,此特定示例中生成的程序集是相同的,但显然它不能证明一般情况。

通常,在 C++ 中,lambda 被认为是低成本或零成本的抽象,如果您认为 lambda 是最干净的代码,那么请使用它。如果您需要,您可以随时快速验证程序集是否相同。不过,您以这种方式使用 lambda 的原因有点不寻常;我不会真的认为代码折叠是一个很好的理由。使用立即计算的 lambdas 的一个更常见的原因是能够const在其他情况下无法使用:

int x;
try {
    x = foo();
}
catch (const ExceptionType& e) {
    x = bar();
} 
Run Code Online (Sandbox Code Playgroud)

对比

const auto x = [] () {
    try {
        return foo();
    }
    catch (const ExceptionType& e) {
        return bar();
    }
}();
Run Code Online (Sandbox Code Playgroud)

x在传统 C++ 代码中持久化外部作用域,我们必须先声明它,然后再分配给它。通过使用返回我们想要的值的 lambda,我们可以同时声明和赋值x,允许它是const.


Ker*_* SB 5

这个问题有点奇怪。编译器不会“删除” lambda,因为 lambda 位于您的源代码中,并且编译器不会修改您的源代码。它的作用是发出机器代码,产生您在源代码中表达的程序的行为。

只要结果的行为符合程序的表达方式,编译器就可以随意发出尽可能多或尽可能少的机器代码。

如果编译器可以将所有代码内联到一个地方,那么它当然不必发出单独的函数体以及它们之间的跳转/调用,这是一种常用的优化。

  • `编译器不会“删除” lambda,因为 lambda 位于源代码中”。我认为 OP 并不是指从字面上删除 lambda 相关的源代码。我将 Q 中的最后一行读为:“编译器能否优化掉由于冗余 lambda 生成的额外机器代码(如果有)?” (5认同)