为什么lambdas可以比纯函数更好地由编译器优化? [英] Why can lambdas be better optimized by the compiler than plain functions?

查看:119
本文介绍了为什么lambdas可以比纯函数更好地由编译器优化?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在他的书 C ++标准库(第二版) Nicolai Josuttis指出,lambdas可以比纯函数更好地由编译器优化。

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.

推荐答案

原因是lambdas是函数对象,因此将它们传递到函数模板将会实例化一个专门为该对象的新功能。编译器因此可以简单地内联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 ,并且可以内联调用它。 (并且调用 map 任何其他lambda将创建一个新的实例化 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可以比纯函数更好地由编译器优化?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆