在其他函数或循环中构造lambda时是否存在性能问题?

时间:2019-04-16 18:19:21

标签: c++ performance c++11 lambda anonymous-function

在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;但是,我还没有找到确切的答案。

4 个答案:

答案 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?)的包装器