在其他函数或循环中构造 lambda 时是不是存在性能问题?
Posted
技术标签:
【中文标题】在其他函数或循环中构造 lambda 时是不是存在性能问题?【英文标题】:Are there performance concerns when constructing lambdas inside other functions or loops?在其他函数或循环中构造 lambda 时是否存在性能问题? 【发布时间】:2019-04-16 18:19:21 【问题描述】:在 javascript 中,Mozilla recommends 如果不需要闭包,则不应在其他函数中创建函数,因为这会对脚本性能产生负面影响。在 JavaScript 中,同样的问题也适用于在循环内创建函数时。同样的问题是否适用于 C++ lambda?
例如,这两个函数之间是否存在性能差异:
int f1(vector<int> v)
for_each(v.begin(), v.end(), [](int i) cout << i << endl; );
auto print_int = [](int i) cout << i << endl; ;
int f2(vector<int> v)
for_each(v.begin(), v.end(), print_int);
我认为是的,这些担忧适用于 C++,并且f2
的性能将优于f1
;但是,我一直没能找到明确的答案。
【问题讨论】:
大多数 lambdas(包括这个)都是微不足道的结构,因此任何体面的编译器都会完全省略构造。 与其他语言不同,所有这些东西都在编译时得到优化。 Lambda 实际上只是语法糖。如果您真的很担心,那么您可以使用this 对其进行基准测试 【参考方案1】:不,是的。
对于简单的 lambda,没关系。这是因为 lambda 是带有 operator() 的类的简单简写。
相关元素是该类具有构造函数。想象一下:
std::map<std::string, std::string> m = create();
auto lambda = [m]() /* code */ ;
在循环中执行此捕获没有意义,因为您复制了许多不应更改的字符串。 在这种情况下,通过引用捕获也可能有意义。
我的建议是:和其他班级一样。如果想构建,只需将其放在您认为合乎逻辑的地方。如果建造成本高昂,请想想为什么这么贵,并在可能的情况下考虑将其移出。
【讨论】:
【参考方案2】:不,现实生活中的编译器不会有性能差异,因为 C++ 编译器可能会为这两个函数生成完全相同的汇编代码。
通常,您不应将专为脚本语言设计的指南应用于编译语言,因为它们在编译阶段发生的事情(因此与运行时性能无关)与运行时发生的事情有很大不同。
【讨论】:
【参考方案3】:这取决于编译器,或者更确切地说,它的优化器。
如果发现它可以内联print_int
,那么f1()
和f2()
的性能将是相同的。
如果没有,那么 f2()
可能会生成一个实际的函数调用(即 x86 汇编器中的 CALL
),而 f1()
可能会内联代码以避免函数调用。
但是,在任何情况下,每次传递都创建“lambda”是极不可能的。 Lambda 只是具有重载函数调用运算符的本地类对象的语法糖。
【讨论】:
我还没有看到编译器内联第一个版本,但不是第二个,反之亦然。 @SergeyA 我也是,但这是可能的。在一些编译器和优化级别上,我确实在生成的代码中发现了一些差异。尽管我在for_each()
而不是 lambda 本身的优化(缺乏)方面有所不同。【参考方案4】:
不,我希望您的代码中的两个示例都不会改变速度。这两个语句对于编译器来说非常相似。
此外,就性能而言,lambda 可能是一个非常危险的构造。根据整个构造,编译器可以或多或少地优化函数调用。使用类似于函数指针的 lambda 会给您带来灾难性的性能结果,例如使用 std::function
作为 lambda 函数指针的包装器(例如 What is the performance overhead of std::function?)
【讨论】:
以上是关于在其他函数或循环中构造 lambda 时是不是存在性能问题?的主要内容,如果未能解决你的问题,请参考以下文章
用于检查特定标签是不是不存在的 Lambda 函数-python