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
等多态包装器时,编译器优化的效率要低得多。编译器可能不会在没有堆省略的情况下优化动态分配的大小,因此它可能会影响可能的优化程度。
如果我处于可以使用任何选项的位置,我应该总是更喜欢其中一个选项而不是其他选项吗?这有什么规定吗?
我想说,永远要选择对你来说最清晰的。如果您关心性能、度量、基准和概要。
你也可以去检查一些代码生成的程序集。