Ill*_*kyi 45 c++ lambda stl c++11
编译器内联lambda函数是否可以提高效率,因为它可以使用简单的标准函数?
例如
std::vector<double> vd;
std::for_each(vd.begin(), vd.end(), [](const double d) {return d*d;});
Run Code Online (Sandbox Code Playgroud)
或者由于缺乏优化而导致效率下降?
第二个问题:我可以在哪里检查我使用的编译器是否优化了内联函数调用,这些函数被发送到算法?我的意思是,如果函数 - 而不是函数对象 - 被发送到算法,最后一个获取指向函数的指针,并且一些编译器优化指向内联函数的指针而其他编译器没有.
Ali*_*Ali 35
在简单的情况下,就像你的例子一样,你应该期望使用lambdas比使用函数指针更好的性能,请参阅
正如其他人已经指出的那样,无法保证你的电话会被内联,但你有更好的机会与lambdas.检查调用是否已内联的一种方法是检查生成的代码.如果您使用的是gcc,请将-S标志传递给编译器.当然,它假定您可以理解汇编代码.
更新于2018年9月11日: Vipul Kumar在他的编辑中指出了两个编译器标志.
GCC -Winline
如果无法内联声明为内联的函数,则发出警告.即使使用此选项,编译器也不会警告系统头中声明的内联函数失败.
编译器使用各种启发式方法来确定是否内联函数.例如,编译器会考虑内联函数的大小以及当前函数中已经完成的内联量.因此,源程序中看似无关紧要的变化可能导致-Winline产生的警告出现或消失.
据我所知,如果你的函数没有内联声明,那么这个编译器标志很可能没有帮助.然而,知道它存在并且部分回答你的第二个问题是很好的.
他指出的另一面旗帜是:
发出优化报告的选项
优化报告从高级别跟踪编译器转换完成的所有主要决策.例如,当内联器决定将函数foo()内联到bar()[...]
我自己没有使用过这个,但基于文档,它可能对您的用例有用.
我个人检查生成的组件,只要它很重要.
Kon*_*lph 26
首先:C++中lambdas设计的重点在于它们与函数调用相比没有开销.这尤其包括可以内联调用它们的事实.
但是这里存在一些概念的混淆:在C++标准中,"内联"是函数的链接,即它是关于如何定义函数的声明,而不是如何调用它.内联定义的函数可以从编译器优化中受益,通过该编译器优化内联调用此类函数.这是一个不同但高度相关的概念.
在lambdas的情况下,被调用的实际函数是一个成员operator(),它被隐式定义为inline编译器为lambda创建的匿名类.lambda的调用被转换为对其的直接调用,operator()因此可以内联.我已经解释了编译器如何在另一个答案中更详细地创建lambda类型.
小智 13
它取决于给编译器的优化级别.例如,这两个函数在语义上是相同的.一种是C++ 11风格,另一种是C风格.
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;
}
Run Code Online (Sandbox Code Playgroud)
使用gcc -O4进行编译会发出两个函数非常相似的代码(不相同但复杂程度相同).
但是,在编译未优化时,lambda不会内联(并且std :: begin和std :: end调用都不是).
因此,虽然编译器可以(并且确实)在要求这样做时优化现代样式代码时做得非常出色,但在未经优化的调试构建中,这种代码可能会或可能会受到性能损失.
| 归档时间: |
|
| 查看次数: |
25874 次 |
| 最近记录: |