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