在JavaScript中,Mozilla recommends如果不需要闭包,则不应在其他函数内创建函数,因为它会对脚本性能产生负面影响。在JavaScript中,当在循环内创建函数时,同样的问题也适用。同样的问题是否适用于C ++ lambdas?
例如,这两个函数之间是否存在性能差异:
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
;但是,我还没有找到明确的答案。
不,是的。
对于简单的lambda来说,没关系。这是因为lambda是带有operator()的类的简单简写。
相关元素是类具有构造函数。想像:
std::map<std::string, std::string> m = create();
auto lambda = [m]() { /* code */ };
在循环中执行此捕获没有意义,因为您复制了许多不应该更改的字符串。在这种情况下,通过引用捕获也可能有意义。
我的建议是:和其他班级一样做。如果要构造,请将其放置在您认为合乎逻辑的位置。如果建造成本高,请考虑为什么这么贵,并考虑在可能的情况下将其移出。
不,现实生活中的编译器没有性能差异,因为C ++编译器可能会为两个函数生成完全相同的汇编代码。
通常,您不应该将为脚本语言设计的指南应用于编译语言,因为它们在编译阶段(与运行时性能无关)与运行时发生的情况有很大不同。
它取决于编译器,或者更确切地说,取决于它的优化器。
如果它拿起它可以内联print_int
,那么f1()
和f2()
的表现将是相同的。
如果没有,那么,f2()
可能会生成一个实际的函数调用(即x86汇编程序中的CALL
),而f1()
可能会内联代码以避免函数调用。
但是,在任何情况下,每次传递都不太可能创建“lambda”。 Lambda只是具有重载函数调用运算符的本地类对象的语法糖。
不,我希望你的代码中的两个例子都不会对速度做任何改变。两种语句对于编译器都非常相似。
此外,lambdas在性能方面可能是一个非常危险的构造。根据整个构造,编译器可以或多或少地优化函数调用。使用类似函数指针的lambdas会给你带来性能上的灾难性结果,所以例如使用std::function
作为lambda函数指针的包装器(例如What is the performance overhead of std::function?)