5

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

LRESULT CALLBACK proc(HWND hWnd,UINT msg,WPARAM wp,LPARAM lp)
{
    开关(味精)
    {
        案例 WM_CREATE:返回 [&](WPARAM wp, LPARAM lp) {
            do_something(wp, lp);
            返回0;
        }(wp, lp);

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

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

编译器可以检测到多余的 lambda 表达式并删除它们吗?

4

2 回答 2

7

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

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

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

int x;
try {
    x = foo();
}
catch (const ExceptionType& e) {
    x = bar();
} 

对比

const auto x = [] () {
    try {
        return foo();
    }
    catch (const ExceptionType& e) {
        return bar();
    }
}();

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

于 2016-10-05T02:15:02.320 回答
5

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

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

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

于 2016-10-04T23:39:03.643 回答