在他的书C++ 标准库(第二版)
中,Nicolai Josuttis 指出编译器可以比普通函数更好地优化 lambda。
In addition, C++ compilers optimize lambdas better than they do ordinary functions. (Page 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 ()
并且可以简单地内联对它的调用。 (并且使用 any 其他 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
解析为一个特定函数。
关于c++ - 为什么编译器可以比普通函数更好地优化 lambda?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13722426/