Lambda捕获与参数-任何性能差异?


auto lambdaFunction1 = [](someClass& obj, int x){/**/};
auto lambdaFunction2 = [&someClassObj, x](){/**/};

使用lambda捕获变量或将其作为参数传递会有任何性能差异吗?如果我处于可以使用任何选项的位置,我是否总是更喜欢其中一种选择?这有什么规定吗?或者这只是一个喜欢哪一个的问题?

PS:我知道,在相同的情况下,我将没有这样的选择,例如使用stl算法,我问的情况下,我可以同时使用

一个粗略的答案:

您是否在某些时候将lambdas转换为对象(如std::function) ?

如果没有,并且每个lambda都是通过模板使用的,那么很可能都是内联的,这无关紧要。大多数接受lambda参数的STL都是这样工作的,而且非常快。在这种情况下,请使用将来更容易阅读和理解的内容。

如果将其转换为函数对象,则使用常规函数指针而不是std::function更便宜,因为没有动态分配的捕获对象与函数本身一起挂起。

一个更准确的答案:基准测试!

捕获和参数在本质上是不同的,并且以不同的方式进行优化。

让我们看看你的lambdas在引擎盖下:

struct lambdaFunction1_type {
auto operator()(someClass& obj, int x) const { /* ... */ }
} lambrdaFunction1{};
struct lambdaFunction2_type {
someClass& obj;
auto operator()(int x) const { /* ... */ }
} lambdaFunction2{someClassObj};

可以看到,capture的行为类似于类数据成员,而parameter的行为类似于…一个参数。两者都有不同的用途。

两者也使用不同的内联过程。与往常一样,在使用std::function等多态包装器时,编译器优化的效率要低得多。编译器可能不会在没有堆省略的情况下优化动态分配的大小,因此它可能会影响可能的优化程度。

如果我处于可以使用任何选项的位置,我应该总是更喜欢其中一个选项而不是其他选项吗?这有什么规定吗?

我想说,永远要选择对你来说最清晰的。如果您关心性能、度量、基准和概要。

你也可以去检查一些代码生成的程序集。

最新更新