简体   繁体   English

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

[英]C++ lambda expressions - How does the compiler interpret them?

I just starter learning the new features in C++ 11. I was reading about lambdas in C++ Primer (Stanley Lippman) and was experimenting with them. 我刚开始学习C ++ 11中的新功能。我正在阅读C ++ Primer(Stanley Lippman)中的lambdas并正在尝试它们。

I tried the following pieces of code: 我尝试了以下代码:

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

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

This code compiled fine. 这段代码编译得很好。 So I guess lambdas without any captures are just generated as normal functions by the compiler and we can use a normal function pointer to them. 所以我猜没有任何捕获的lambdas只是由编译器生成为普通函数,我们可以使用它们的普通函数指针。

Now I changed the code to use captures: 现在我更改了代码以使用捕获:

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

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

But this failed to compile. 但这无法编译。 I got the following compilation error while using g++: 使用g ++时出现以下编译错误:

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

From the error I can understand that it is not a normal function that is generated and it might probably be a class with an overloaded call-operator. 从错误中我可以理解,它不是生成的普通函数,它可能是一个带有重载调用操作符的类。 Or is it something else? 或者是别的什么?

My questions : How does the compiler handle lambdas internally? 我的问题:编译器如何在内部处理lambdas? How should I pass around lambdas that use captures ie what should be the return value from func()? 我应该如何传递使用捕获的lambda,即func()的返回值应该是什么? I cant currently think of a use case where I would need to use lambdas like this but I just want to understand more about them. 我目前无法想到一个用例,我需要使用这样的lambdas,但我只是想了解更多关于它们的信息。 Please help. 请帮忙。

Thanks. 谢谢。

All lambdas are function objects with implementation defined type called closure type with a operator() member. 所有lambda都是具有实现定义类型的函数对象,称为闭包类型 ,带有operator()成员。 Every lambda expression has it's own unique closure type, too. 每个lambda表达式都有自己独特的闭包类型。

Lambdas without a capture can be converted to a function pointer. 没有捕获的Lambda可以转换为函数指针。 Whether or not compiler generates a normal function behind the scenes is an internal detail and shouldn't matter to you. 编译器是否在幕后生成正常函数是一个内部细节,对您来说无关紧要。

It's not possible to return a lambda that's defined inside a function. 无法返回在函数内定义的lambda。 There are few things that prevent this - you don't know the name of a type of lambda expression, you can't use a lambda expression inside a decltype and as already said, two lambda expressions (even if lexically identical) have different types. 很少有东西阻止这种情况 - 你不知道一种lambda表达式的名称,你不能在decltype使用lambda表达式,正如已经说过的,两个lambda表达式(即使词法相同)有不同的类型。

What you can do is use std::function : 你可以做的是使用std::function

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

This way works with captures, too. 这种方式也适用于捕获。

Or something like this: 或类似的东西:

auto f = []{ return 0; };

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

EDIT: The upcoming C++1y standard (more specifically, return type deduction), however, will allow you to do this: 编辑:然而,即将推出的C ++ 1y标准(更具体地说,返回类型扣除)将允许您这样做:

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

Compiler is free to decide how to generate the type of a lambda function. 编译器可以自由决定如何生成lambda函数的类型。 It generates a function object that means you can invoke it by () . 它生成一个函数对象,这意味着您可以通过()调用它。 But the type can be different in various situations. 但是在各种情况下类型可能不同。 Every single lambda can has a unique type. 每一个lambda都可以有一个独特的类型。 A simple lambda (doesn't capture anything) can be stored in a pointer to function. 一个简单的lambda(不捕获任何东西)可以存储在指向函数的指针中。

In C++11, to wrap a lambda which captures data, you can use std::function : 在C ++ 11中,要包装捕获数据的lambda,可以使用std::function

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

In C++14, it has function return type deduction , let the compile handle it: 在C ++ 14中,它有函数返回类型推导 ,让编译处理它:

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

A function cannot return a lambda function itself. 函数本身不能返回lambda函数。 If you write: 如果你写:

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

Then GCC complains: 然后海湾合作委员会抱怨:

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

So the solution is to wrap the return object into a std::function : 所以解决方案是将返回对象包装到std::function

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

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM