Lambda 优化和内联函数:编译器的优势
Nicolai Josuttis 的声明(与普通函数相比,lambda 表现出卓越的编译器优化)引起了许多人的兴趣开发商。通过调查这一说法,我们试图揭示这种优化优势背后的根本原因。
函数对象和内联
作为函数对象的 Lambda 拥有一个关键优势:将它们传递给函数模板会触发专门为该 lambda 定制的函数的实例化。这允许编译器毫不费力地内联 lambda 调用。
相反,函数在传递给函数模板时使用函数指针。传统上,编译器在通过函数指针内联调用时遇到挑战。仅当封闭函数本身内联时,内联优化才是可行的。
模板实例化:探索差异
为了说明这种差异,请考虑映射函数模板:
templatevoid 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* begin, int* end, _some_lambda_type f) { for (; begin != end; begin) *begin = f.operator()(*begin); }
编译器识别 _some_lambda_type::operator() 函数并可以直接内联调用它。每个不同的 lambda 类型都会提示映射的新实例化,从而保证特定于 lambda 的优化。
相反,使用函数指针调用映射会产生以下实例化:
template void map(int* begin, int* end, int (*f)(int)) { for (; begin != end; begin) *begin = f(*begin); }
这里,函数指针 f 指向每个映射调用的不同地址,从而禁止内联优化。必须内联对 map 的调用,编译器才能将 f 解析为特定函数。
因此,lambda 作为函数对象的独特性及其促进模板实例化的能力使编译器具有比传统函数调用更强的优化能力通过指针。
免责声明: 提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发到邮箱:[email protected] 我们会第一时间内为您处理。
Copyright© 2022 湘ICP备2022001581号-3