首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >lambdas和C++中的函数一样内联吗?

lambdas和C++中的函数一样内联吗?
EN

Stack Overflow用户
提问于 2013-04-10 23:57:06
回答 3查看 39.2K关注 0票数 64

编译器能否内联lambda函数来提高效率,就像使用简单的标准函数一样?

例如:

代码语言:javascript
复制
std::vector<double> vd;
std::for_each(vd.begin(), vd.end(), [](const double d) {return d*d;});

或者是由于缺乏优化而导致的效率损失?

第二个问题:我在哪里可以检查我使用的编译器是否优化了内联函数的调用,这些函数被发送到一个算法?我的意思是,如果一个函数--而不是一个函数对象--被发送给一个算法,那么最后一个函数就会得到一个指向该函数的指针,一些编译器会优化指向内联函数的指针,而另一些编译器则不会。

EN

回答 3

Stack Overflow用户

发布于 2013-04-11 00:54:59

在简单的情况下,如您的示例,您应该期望使用lambda比使用函数指针更好的性能,请参阅

Why can lambdas be better optimized by the compiler than plain functions?

正如其他人已经指出的那样,不能保证您的调用是内联的,但使用lambdas的机会更大。检查调用是否已内联的一种方法是检查生成的代码。如果您使用的是gcc,请将-S标志传递给编译器。当然,它假设您能够理解汇编代码。

2018年9月11日更新: Vipul Kumar在他的编辑中指出了两个编译器标志。

GCC -Winline

如果声明为内联的函数不能内联,则

发出警告。即使使用此选项,编译器也不会警告系统头中声明的内联函数失败。

编译器使用各种启发式方法来确定是否内联函数。例如,编译器会考虑正在内联的函数的大小以及当前函数中已经完成的内联数量。因此,源程序中看似微不足道的更改可能会导致-Winline产生的警告出现或消失。

据我所知,如果你的函数没有内联声明,这个编译器标志很可能没有用。然而,知道它的存在是件好事,它部分地回答了你的第二个问题。

他指出的另一面旗帜是:

Clang -Rpass=inline

用于发出优化报告的

选项

优化报告在高层次上跟踪由编译器转换完成的所有主要决策。例如,当内联程序决定将foo()函数内联到bar()中时...

我自己没有用过这个,但根据文档,它可能对你的用例很有用。

每当生成的程序集如此重要时,我都会亲自检查它。

票数 45
EN

Stack Overflow用户

发布于 2013-04-11 01:21:25

首先: C++中lambdas设计的全部要点是,与函数调用相比,它们没有开销。值得注意的是,对它们的调用可以内联。

但是这里有一个概念混乱:在C++标准中,“inline” is the of a function, i.e. it is a statement about how a function is ,而不是它是如何被调用的。内联定义的函数可以从编译器优化中受益,通过这种优化,对这些函数的调用被内联。这是一个不同但高度相关的概念。

对于lambda,实际调用的函数是一个成员operator(),它在由lambda编译器创建的匿名类中被隐式定义为inline。lambda的调用被转换为对其operator()的直接调用,因此可以内联。I’ve explained how the compiler creates lambda types in more detail in another answer

票数 42
EN

Stack Overflow用户

发布于 2013-09-13 20:09:14

这取决于提供给编译器的优化级别。例如,这两个函数在语义上是相同的。一种是C++11风格,另一种是C风格。

代码语言:javascript
复制
void foo1 (void)
{
    int arr[100];
    std::generate(std::begin(arr), std::end(arr), [](){return std::rand()%100;});
}

void foo2 (void)
{
    int arr[100];
    for (int *i = arr; i < arr+100; i++) *i = std::rand()%100;
}

用gcc -O4编译这段代码时,这两个函数的代码非常相似(不完全相同,但复杂度相当)。

但是,在编译未优化的代码时,lambda不是内联的( std::begin和std::end调用也是如此)。

因此,尽管编译器可以(并且确实)在优化现代风格的代码方面做了出色的工作,但在未优化的调试版本中,这类代码可能会或可能会有性能损失。

票数 15
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/15930755

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档