Why can lambdas be better optimized by the compiler than plain functions?(为什么编译器可以比普通函数更好地优化 lambdas?)
问题描述
在他的书中 The C++ Standard Library (Second Edition)
Nicolai Josuttis 指出,与普通函数相比,编译器可以更好地优化 lambda.
In his book The C++ Standard Library (Second Edition)
Nicolai Josuttis states that lambdas can be better optimized by the compiler than plain functions.
此外,C++ 编译器比它们更好地优化了 lambda普通功能.(第 213 页)
In addition, C++ compilers optimize lambdas better than they do ordinary functions. (Page 213)
这是为什么?
我认为内联应该不再有任何区别.我能想到的唯一原因是编译器可能有更好的 lambda 本地上下文,这样可以做出更多假设并执行更多优化.
I thought when it comes to inlining there shouldn't be any difference any more. The only reason I could think of is that compilers might have a better local context with lambdas and such can make more assumptions and perform more optimizations.
推荐答案
原因是 lambda 是函数对象,因此将它们传递给函数模板将实例化一个专门用于该对象的新函数.因此,编译器可以轻松地内联 lambda 调用.
The reason is that lambdas are function objects so passing them to a function template will instantiate a new function specifically for that object. The compiler can thus trivially inline the lambda call.
另一方面,对于函数,旧的警告适用:函数指针被传递给函数模板,并且编译器传统上有很多问题通过函数指针内联调用.它们理论上可以被内联,但前提是周围的函数也被内联.
For functions, on the other hand, the old caveat applies: a function pointer gets passed to the function template, and compilers traditionally have a lot of problems inlining calls via function pointers. They can theoretically be inlined, but only if the surrounding function is inlined as well.
例如,考虑以下函数模板:
As an example, consider the following function template:
template <typename Iter, typename F>
void map(Iter begin, Iter end, F f) {
for (; begin != end; ++begin)
*begin = f(*begin);
}
像这样用 lambda 调用它:
Calling it with a lambda like this:
int a[] = { 1, 2, 3, 4 };
map(begin(a), end(a), [](int n) { return n * 2; });
此实例化的结果(由编译器创建):
Results in this instantiation (created by the compiler):
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 都有不同的类型.)
… the compiler knows _some_lambda_type::operator ()
and can inline calls to it trivially. (And invoking the function map
with any other lambda would create a new instantiation of map
since each lambda has a distinct type.)
但是当使用函数指针调用时,实例化如下所示:
But when called with a function pointer, the instantiation looks as follows:
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
解析为一个特定的函数.
… and here f
points to a different address for each call to map
and thus the compiler cannot inline calls to f
unless the surrounding call to map
has also been inlined so that the compiler can resolve f
to one specific function.
这篇关于为什么编译器可以比普通函数更好地优化 lambdas?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:为什么编译器可以比普通函数更好地优化 lambdas?
基础教程推荐
- 为 C/C++ 中的项目的 makefile 生成依赖项 2022-01-01
- 在 C++ 中循环遍历所有 Lua 全局变量 2021-01-01
- 如何“在 Finder 中显示"或“在资源管理器中显 2021-01-01
- 如何使图像调整大小以在 Qt 中缩放? 2021-01-01
- 使用从字符串中提取的参数调用函数 2022-01-01
- Windows Media Foundation 录制音频 2021-01-01
- 管理共享内存应该分配多少内存?(助推) 2022-12-07
- 如何在不破坏 vtbl 的情况下做相当于 memset(this, ...) 的操作? 2022-01-01
- 为什么语句不能出现在命名空间范围内? 2021-01-01
- 从 std::cin 读取密码 2021-01-01