Nicolai Josuttis在他的书中The C++ Standard Library (Second Edition)指出,编译器可以比普通函数更好地优化 lambda。
The C++ Standard Library (Second Edition)
此外,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 ()并且可以简单地内联对它的调用。map(并且使用 任何 其他 lambda调用该函数将创建一个新的实例化 ,map因为每个 lambda 都有不同的类型。)
_some_lambda_type::operator ()
map
但是当使用函数指针调用时,实例化如下所示:
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到一个特定的函数。
f