“Lambda 很便宜” - 真的吗?在什么情况下?

skt*_*pin 1 c++ lambda c++14

这篇文章宣称使用 C++ Lambdas 是“便宜的”: Lambdas 不是魔法 - 第 2 部分

他们演示了如何将 lambda 传递给现有的 std 函数/模板。一篇文章演示了如何使用“auto”作为函数的返回类型以在不使用 std::function 的情况下返回 lambda。

我看到的任何文章都没有演示如何制作自己的函数,尤其是。类成员函数,采用 lambda 或更多,不使用 std::function。

所以这个大胆的“lambdas 很便宜”的声明 - 在现实世界的场景中真的是这样吗?

作为参考:“便宜”对我来说是为了解决这个问题:在具有数百 KB 内存和两位数 MHz 速度的嵌入式裸机项目中非常有用。(我一直在该领域使用 C++ 的一个健全的子集,并且正在寻找我可以使用的其他内容)

据我所知, std::function<> 并不便宜。一方面,作为 std::function 传递的 Lambda 显然无法再进行内联优化。但更糟糕的是, std::function<> 是 32 字节大。同样显然,如果捕获的超过适合,可能会使用动态分配?这一切听起来像是个坏消息。

因此,虽然我正在寻找不使用 std::function 使用 lambdas 的方法,并且只找到一个返回 auto 的示例,但我尝试了这个:我制作了一个非常简单的类,它使用“auto”作为成员函数中的参数类型,以及编译器似乎对它很满意(尽管它不像 std::function 就预期的函子参数而言是“自记录”代码)。

struct FuncyClass
{   unsigned func(auto fnx)
    {   return 2 * fnx(7);
    }
};

int main()
{   FuncyClass fc;
    auto result = fc.func( [](auto x){return x*3;} );
    
    printf("Result: %u\n", result);
    return 0;
}
// Output: "Result: 42"
Run Code Online (Sandbox Code Playgroud)

但我有一种感觉,这个非常简单的场景并没有向我展示当它被更复杂的场景使用时可能出现的编译器错误泛滥。我不太明白这个语法在幕后发生了什么,编译器在确定时做什么,从函子的使用,什么参数和返回类型是预期的,以及这个带有自动参数的函数是如何在幕后实现的.

,即使用自动输入指定参数时,真的让你的类的成员函数的λ-定制一种合适的方式?然后它看起来“便宜”,因为在我的测试中,当使用 auto 而不是 std::function 时,可执行文件要小得多。

当然,它仍然是有限的:如果不使用 std::function<>(或类似的 DIY 包装器),类就无法保留 lambda,对吗?是否有可能阻止动态分配的发生,例如,当出现需要 std::function 分配内存的情况时,使其成为编译时错误?

Ayx*_*xan 7

Lambda 只是重载operator(). 您可以从概念上将它们视为等价于:

class Lamba {
public:
    auto operator()(...) const { /* ... */ }
};
Run Code Online (Sandbox Code Playgroud)

因此,它们并不比类似的函数调用更昂贵。std::function没有必要使用 lambdas。您可以使用类型推导来存储/传递它们:

template <typename Func>
void foo(Func&& func) { /* ... */ }
Run Code Online (Sandbox Code Playgroud)

对于非捕获 lambda,您可以使用以下命令将它们隐式或显式转换为函数指针operator+

void (*fp)(int) = [](int){ /* ... */ };
Run Code Online (Sandbox Code Playgroud)

你的问题很难回答的原因是你在问 lambda 是否很昂贵。但是,相比之下呢?如果您想知道它们在您的特定情况下是否具有足够的性能,您将不得不为自己做一些分析并弄清楚。