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

标签 c++ c++11 lambda

我刚刚开始学习 C++ 11 中的新功能。我在 C++ Primer (Stanley Lippman) 中阅读了有关 lambda 的内容,并用它们进行了试验。

我尝试了以下代码:

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() 的返回值应该是什么?我目前想不出我需要像这样使用 lambda 的用例,但我只想了解更多关于它们的信息。请帮忙。

谢谢。

最佳答案

所有 lambda 都是具有实现定义类型的函数对象,称为 闭包类型 和一个 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; };   
}

关于C++ lambda 表达式 - 编译器如何解释它们?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22894157/

相关文章:

c++ - 如何在运算符重载中忽略空格输入流>>

c++ - 函数不会更改 C++ 中的对象属性

c++ - 不要打印尾随定界符 stream_iterator C++

c++ - 从 lambda 返回 Eigen::Map

c# - Lambda 表达式 "IN"运算符存在?

c++ - operator++() nothrow 不编译

c++ - FLTK GUI 不显示 (Dev-C++)

c++ - 成员函数模板,其参数数量取决于一个完整的模板参数

c++ - 检查类模板是否已实例化?

java - 为什么这个程序会产生这个结果?