为什么lambda可以通过编译器比普通函数更好地优化?
在他的书The C++ Standard Library (Second Edition)
Nicolai Josuttis指出,编译器可以比普通函数更好地优化lambda表达式。
另外,C ++编译器比普通函数更好地优化lambda表达式。 (页213)
这是为什么?
我认为当谈到内联时,应该没有任何区别了。 我能想到的唯一原因是编译器可能对lambda表达式有更好的本地环境,这样可以做出更多的假设并执行更多的优化。
原因是lambda是函数对象,因此将它们传递给函数模板将实例化一个专门用于该对象的新函数。 编译器可以轻松地内联lambda调用。
另一方面,对于函数,旧的注意事项适用:函数指针传递给函数模板,编译器通过函数指针传入内联函数时会遇到很多问题。 理论上讲,它们可以内联,但前提是内联函数也是内联的。
作为一个例子,考虑下面的函数模板:
template <typename Iter, typename F>
void map(Iter begin, Iter end, F f) {
for (; begin != end; ++begin)
*begin = f(*begin);
}
用这样的lambda来调用它:
int a[] = { 1, 2, 3, 4 };
map(begin(a), end(a), [](int n) { return n * 2; });
结果在这个实例中(由编译器创建):
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 ()
并且可以内联地调用它。 (并且用任何其他lambda调用函数map
会创建一个新的map
实例,因为每个lambda具有不同的类型。)
但是当用函数指针调用时,实例化看起来如下所示:
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
解析为一个特定函数。
因为当你向算法传递一个“函数”时,你实际上传递了一个指向函数的指针,所以它必须通过指向该函数的指针进行间接调用。 当你使用一个lambda表达式时,你将一个对象传递给一个专门为该类型实例化的模板实例,并且对lambda函数的调用是直接调用,而不是通过函数指针调用,因此可能更有可能被内联。
链接地址: http://www.djcxy.com/p/85707.html上一篇: Why can lambdas be better optimized by the compiler than plain functions?