lambda表达式是内联类似于C ++函数?(Are lambdas inlined like fu

2019-08-21 10:15发布

能够/确实编译器内联波长的职能,以提高效率,因为它可能会用简单的标准功能?

std::vector<double> vd;
std::for_each(vd.begin(), vd.end(), [](const double d) {return d*d;});

还是有不足造成的优化效率的损失?

第二个问题:在哪里可以查,如果我使用的编译器优化了内联函数的调用,将其发送到一个算法? 我的意思是,如果一个函数不是一个函数对象被发送到一个算法,最后一个获得一个函数指针,以及一些编译器优化指针内联函数和别人不一样。

Answer 1:

在简单情况下,比如你的例子, 你应该期望与lambda表达式比函数指针更好的性能,

为什么lambda表达式编译器比普通的功能得到更好的优化?

正如其他人已经指出的,没有保证您的通话将被内联,但你有lambda表达式更好的机会。 检查电话是否已经被内联的一种方法是检查生成的代码。 如果你正在使用gcc,通过-S标志编译器。 当然,假设你能理解的汇编代码。



更新2018年9月11日: VIPUL库马尔在他的编辑指出了两次编译器标志。

GCC -Winline

警告如果被声明为内联函数无法被内联。 即使有这个选项,编译器不会发出警告故障在系统头文件中声明的内联函数。

编译器使用各种启发式,以确定是否要内联函数。 例如,编译器需要考虑被内联函数的大小以及已经在当前的功能做了内联的量。 因此,在源程序中看似微不足道的变化会引起通过-Winline产生的出现或消失的警告。

据我了解这一点,如果你的功能不联声明,这个编译器标志是最有可能没有帮助。 不过这是好事,知道它的存在,它部分地回答你的第二个问题。

他指出,另一个标志是:

-Rpass=inline

选项发出优化报告

优化报告跟踪,在一个高的水平,全部由编译器转换完成的重大决策。 例如,当内衬确定内联函数foo()到bar()[...]

我没有使用过这一个自己,但基于它可能是你的使用情况非常有用的文档上。

我亲自检查生成的程序集时,它是非常重要的。



Answer 2:

第一关:在C ++ lambda表达式设计的整点是,他们没有的开销相比,函数调用。 这主要是包括调用它们可内联的事实。

但还有这里的概念混淆:在C ++标准, “内联”是一个功能的联动 ,即它是一个关于一个功能是如何定义的声明 ,而不是如何被调用。 被行内定义的函数可以受益于通过调用这些函数都是内联编译器优化。 这是一个不同但高度相关的概念。

在lambda表达式的情况下,被称为实际功能是其成员operator()被隐式地定义为inline在编译器为拉姆达创建匿名类。 拉姆达的通话将被转换为直接到了它的电话operator()因此被内联。 我已经解释了编译器在另一个答案更详细的创建拉姆达类型 。



Answer 3:

这取决于向编译器优化级别。 举个例子,这两个功能,其具有相同的语义。 一个是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;
}

用gcc -O4编译此发出用于两个功能码,这是非常相似的(不相同,但复杂性当量)。

但是,编译未优化时的拉姆达没有内联(也不是的std ::开始和std ::结束通话)。

因此,尽管编译器可以(而且不会)做在当被问及这样做优化现代风格的代码非常出色,有可能或或许将成为这种代码在优化调试构建一个性能损失。



文章来源: Are lambdas inlined like functions in C++?