自执行C ++ 11 lambda的成本

时间:2016-10-04 23:33:31

标签: c++ c++11 lambda switch-statement self-executing-function

window procedure中,我正在使用自执行的lambdas编写switch语句,如下所示:

LRESULT CALLBACK proc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
{
    switch (msg)
    {
        case WM_CREATE: return [&](WPARAM wp, LPARAM lp) {
            do_something(wp, lp);
            return 0;
        }(wp, lp);

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

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

编译器是否可以检测冗余lambda并将其删除?

2 个答案:

答案 0 :(得分:3)

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

只要结果与程序表达的方式相同,编译器就可以随意发出尽可能多的机器代码。

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

答案 1 :(得分:3)

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

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

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

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

VS

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

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