Lambda 优化和内联函数:编译器的优势
Nicolai Josuttis 的说法(与普通函数相比,lambda 表现出卓越的编译器优化)引起了许多人的兴趣开发商。通过调查这一说法,我们试图揭示这种优化优势背后的根本原因。
函数对象和内联
作为函数对象的 Lambda 拥有一个关键优势:将它们传递给函数模板会触发专门为该 lambda 定制的函数的实例化。这允许编译器毫不费力地内联 lambda 调用。
相反,函数在传递给函数模板时使用函数指针。传统上,编译器在通过函数指针内联调用时遇到挑战。仅当封闭函数本身内联时,内联优化才是可行的。
模板实例化:探索差异
为了说明这种差异,请考虑映射函数模板:
template <typename Iter, typename F> void map(Iter begin, Iter end, F f) { for (; begin != end; ++begin) *begin = f(*begin); }
使用 a 调用它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 类型都会提示映射的新实例化,从而保证特定于 lambda 的优化。
相反,使用函数指针调用 map 会产生以下实例化:
template <> void map<int*, int (*)(int)>(int* begin, int* end, int (*f)(int)) { for (; begin != end; ++begin) *begin = f(*begin); }
这里,函数指针 f 指向每个映射调用的不同地址,从而禁止内联优化。必须内联对 map 的调用,编译器才能将 f 解析为特定函数。
因此,lambda 作为函数对象的独特性及其促进模板实例化的能力使编译器具有比传统函数调用更强的优化能力通过指针。
以上是为什么编译器优化 lambda 函数比传统函数更有效?的详细内容。更多信息请关注PHP中文网其他相关文章!