首页 > 后端开发 > C++ > 编译器可以比普通函数更好地优化 Lambda 吗?

编译器可以比普通函数更好地优化 Lambda 吗?

Mary-Kate Olsen
发布: 2024-11-19 18:33:03
原创
237 人浏览过

Can Lambdas Be Optimized Better Than Plain Functions By Compilers?

Lambda 与普通函数的编译器优化

Nicolai Josuttis 在他的书《C 标准库(第二版)》中声称编译器可以比普通函数更好地优化 lambda。考虑到 lambda 表达式和普通函数都可以内联,这似乎有悖常理。但是,两者之间存在细微差别,可以在 lambda 的情况下进行更好的优化。

区别:函数对象与函数指针

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);
}
登录后复制

编译器可以识别 lambda 的 operator() 以及对其进行简单的内联调用。

但是当用函数指针调用时:

map(begin(a), end(a), &multiply_by_two);
登录后复制

实例化变成:

template <>
void map<int*, int (*)(int)>(int* begin, int* end, int (*f)(int)) {
    for (; begin != end; ++begin)
        *begin = f(*begin);
}
登录后复制

这里,每次调用map时f都会引用不同的函数,防止编译器不会进行内联调用,除非 map 本身是内联的。

结论

作为函数对象的 lambda 的独特类型使编译器能够创建特定的函数实例化并无缝内联其调用。这种增强的优化功能将 lambda 与普通函数区分开来,使它们成为提高代码性能和效率的首选。

以上是编译器可以比普通函数更好地优化 Lambda 吗?的详细内容。更多信息请关注PHP中文网其他相关文章!

来源:php.cn
本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
作者最新文章
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板