C ++ lambda表达式 - 编译器如何解释它们?

时间:2014-04-06 12:40:13

标签: c++ c++11 lambda

我刚开始学习C ++ 11中的新功能。我正在阅读C ++ Primer(Stanley Lippman)中的lambdas并正在尝试它们。

我尝试了以下代码:

auto func() -> int (*) (){
    //int c=0;
    return []()-> int {return 0;};
}

int main(){
    auto p = func();
}

这段代码编译得很好。所以我猜没有任何捕获的lambdas只是由编译器生成为普通函数,我们可以使用它们的普通函数指针。

现在我更改了代码以使用捕获:

auto func() -> int (*) (){
    int c=0;
    return [=]()-> int {return c;};
}

int main(){
    auto p = func();
}

但这无法编译。使用g ++时出现以下编译错误:

main.cpp: In function ‘int (* func())()’:
main.cpp:6:31: error: cannot convert ‘func()::__lambda0’ to ‘int (*)()’ in return
return [=]()-> int {return c;};

从错误我可以理解,它不是一个正常的函数,它可能是一个带有重载调用运算符的类。还是别的什么?

我的问题:编译器如何在内部处理lambdas?我应该如何传递使用捕获的lambda,即func()的返回值应该是什么?我目前无法想到一个用例,我需要使用这样的lambdas,但我只是想了解更多关于它们的信息。请帮忙。

感谢。

3 个答案:

答案 0 :(得分:9)

所有lambdas都是具有实现定义类型的函数对象,名为闭包类型,带有operator()成员。每个lambda表达式都有它自己独特的闭包类型。

没有捕获的Lambda可以转换到函数指针。编译器是否在幕后生成正常函数是一个内部细节,对您来说无关紧要。

无法返回在函数内定义的lambda。很少有东西阻止这种情况 - 你不知道一种lambda表达式的名称,你不能在decltype内使用lambda表达式,并且已经说过,两个lambda表达式(即使词法相同) )有不同的类型。

您可以使用std::function

std::function<int()> func()
{
    int i = 0;
    return [=]()-> int {return i;};
}

这种方式也适用于捕获。

或类似的东西:

auto f = []{ return 0; };

auto func() -> decltype(f)
{
    return f;
}

编辑:然而,即将推出的C ++ 1y标准(更具体地说,返回类型扣除)将允许您这样做:

auto func()
{
    int i = 42;
    return [=]{ return i; };   
}

答案 1 :(得分:2)

编译器可以自由决定如何生成lambda函数的类型。它生成一个函数对象,这意味着您可以通过()调用它。但是在各种情况下类型可能不同。每一个lambda都可以有一个独特的类型。一个简单的lambda(不捕获任何东西)可以存储在指向函数的指针中。

在C ++ 11中,要包装捕获数据的lambda,可以使用std::function

auto func() -> std::function<int()> {
    int c = 0;
    return [=]()-> int {return c;};
}

在C ++ 14中,它有function return type deduction,让编译处理它:

auto func() {
    int c = 0;
    return [=]()-> int {return c;};
}

答案 2 :(得分:2)

函数本身不能返回lambda函数。如果你写:

auto func() -> int () {
    int c=0;
    return [=]()-> int {return c;};
}
然后GCC抱怨说:

lambda.cpp:3:21: error: function return type cannot be function
 auto func() -> int (){

所以解决方法是将返回对象包装到std::function

#include <functional>
    auto func() -> std::function<int ()> {
    int c=0;
    return [=]()-> int {return c;};
}

int main(){
    auto p = func();
}