问题描述
在他的书 C ++标准库(第二版)
Nicolai Josuttis指出,lambdas可以比纯函数更好地由编译器优化。
In his book The C++ Standard Library (Second Edition)
Nicolai Josuttis states that lambdas can be better optimized by the compiler than plain functions.
为什么?
我想当谈到内联时,应该没有什么区别了。我可以想到的唯一原因是编译器可能有一个更好的本地上下文与lambda,这样可以做出更多的假设和执行更多的优化。
I thought when it comes to inlining there shouldn't be any difference any more. The only reason I could think of is that compilers might have a better local context with lambdas and such can make more assumptions and perform more optimizations.
推荐答案
原因是lambdas是函数对象,因此将它们传递到函数模板将会实例化一个专门为该对象的新功能。编译器因此可以简单地内联lambda调用。
The reason is that lambdas are function objects so passing them to a function template will instantiate a new function specifically for that object. The compiler can thus trivially inline the lambda call.
对于函数,另一方面,旧的警告适用:函数到函数模板,并且编译器传统上有很多问题通过函数指针内联调用。
For functions, on the other hand, the old caveat applies: a function pointer gets passed to the function template, and compilers traditionally have a lot of problems inlining calls via function pointers. They can theoretically be inlined, but only if the surrounding function is inlined as well.
例如,考虑下面的函数模板:
As an example, consider the following function template:
template <typename Iter, typename F>
void map(Iter begin, Iter end, F f) {
for (; begin != end; ++begin)
*begin = f(*begin);
}
使用lambda调用它:
Calling it with a lambda like this:
int a[] = { 1, 2, 3, 4 };
map(begin(a), end(a), [](int n) { return n * 2; });
此实例化中的结果(由编译器创建):
Results in this instantiation (created by the compiler):
template <>
void map<int*, _some_lambda_type>(int* begin, int* end, _some_lambda_type f) {
for (; begin != end; ++begin)
*begin = f.operator()(*begin);
}
...编译器知道 _some_lambda_type :: operator
,并且可以内联调用它。 (并且调用 map
与任何其他lambda将创建一个新的实例化 map
因为每个lambda都有一个不同的类型。)
… the compiler knows _some_lambda_type::operator ()
and can inline calls to it trivially. (And invoking the function map
with any other lambda would create a new instantiation of map
since each lambda has a distinct type.)
但是当使用函数指针调用时,实例化如下:
But when called with a function pointer, the instantiation looks as follows:
template <>
void map<int*, int (*)(int)>(int* begin, int* end, int (*f)(int)) {
for (; begin != end; ++begin)
*begin = f(*begin);
}
...此处 f
指向 map
的每个调用的不同地址,因此编译器不能内联对 f
的调用,除非周围的调用到 map
也被内联,以便编译器可以解析 f
到一个特定的函数。
… and here f
points to a different address for each call to map
and thus the compiler cannot inline calls to f
unless the surrounding call to map
has also been inlined so that the compiler can resolve f
to one specific function.
这篇关于为什么lambdas可以比纯函数更好地由编译器优化?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!