C++;lambda表达式-编译器如何解释它们? 我刚刚开始学习C++ 11中的新特性。我正在阅读关于C++引物(Stanley Lippman)中的lambdas,并在实验中使用。

C++;lambda表达式-编译器如何解释它们? 我刚刚开始学习C++ 11中的新特性。我正在阅读关于C++引物(Stanley Lippman)中的lambdas,并在实验中使用。,c++,c++11,lambda,C++,C++11,Lambda,我尝试了以下代码: auto func() -> int (*) (){ //int c=0; return []()-> int {return 0;}; } int main(){ auto p = func(); } 这段代码编译得很好。因此,我猜没有任何捕获的lambda只是由编译器作为普通函数生成的,我们可以使用一个普通函数指针指向它们 现在我将代码更改为使用捕获: auto func() -> int (*) (){ int c=

我尝试了以下代码:

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

int main(){
    auto p = func();
}
这段代码编译得很好。因此,我猜没有任何捕获的lambda只是由编译器作为普通函数生成的,我们可以使用一个普通函数指针指向它们

现在我将代码更改为使用捕获:

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;};
从这个错误中,我可以理解它不是生成的普通函数,它可能是一个具有重载调用运算符的类。还是别的什么

我的问题:编译器如何在内部处理lambda?我应该如何传递使用捕获的lambda,即func()的返回值应该是什么?我现在想不出一个需要像这样使用lambdas的用例,但我只是想对它们有更多的了解。请帮忙


谢谢。

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

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


函数本身不能返回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();
}
std::function<int()> func()
{
    int i = 0;
    return [=]()-> int {return i;};
}
#包括
auto func()->std::function{
int c=0;
return[=]()->int{return c;};
}
int main(){
自动p=func();
}

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

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

不可能返回在函数中定义的lambda。有几件事可以防止这种情况发生-您不知道lambda表达式类型的名称,您不能在
decltype
中使用lambda表达式,正如前面所说的,两个lambda表达式(即使在词汇上相同)具有不同的类型

您可以使用
std::function

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

int main(){
    auto p = func();
}
std::function<int()> func()
{
    int i = 0;
    return [=]()-> int {return i;};
}
编辑:即将推出的C++1y标准(更具体地说,返回类型扣除)将允许您执行以下操作:

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

尝试此链接:唯一提到转换为函数指针的答案+请注意,您可以通过返回类型推断从lambda返回lambda,在C++1y中也可以从函数返回lambda。lambda表达式的类型从来不是任何可观察行为的函数类型(当然,它通常作为(成员)函数实现)。例如,保证lambda不会匹配模板类型推断中的某些泛型
Ret(Params…
。@dyp正确,谢谢。我更新了一个返回类型推断示例。非捕获lambda不能存储在函数指针中:它们可以转换为函数指针。@Yakk:你能解释一下
被存储
被转换
之间的区别吗?如果您的意思是在存储指向函数的指针之前将强制转换非捕获lambda,那么您就错了。lambda没有特定的类型,谁知道呢,也许编译器对简单的lambda使用指向函数类型的指针,它们可以直接分配给指向函数的指针。保证lambda与指向函数
模板
函数的指针不匹配。所以不,我不相信你是对的。实际上,每个编译器都使用生成的唯一类型,这使得调用的inlinimg变得微不足道:函数指针使inlinimg变得棘手和脆弱。因此,在理论上,在实践中,这是一种向具有不同性质的不同类型的转化。
auto func()
{
    int i = 42;
    return [=]{ return i; };   
}