简体   繁体   English

为什么 cpp std::function 可以保存捕获 lambda,而 function 指针不能?

[英]Why cpp std::function can hold capture-lambda, while function pointer cannot?

I've got this code snippet:我有这个代码片段:

    int x = 3;
    auto fauto = [=](){ cout<<'x'; };
    function<void()> func{fauto};
    func();
    void (*rawPf)() = fauto; // fail to compile
    rawPf();

I knew the syntax that only non-capture lambda can be assigned to function pointer.我知道只有非捕获 lambda 可以分配给 function 指针的语法。 But:但:

(1) Why std::function can hold capture-lambda? (1) 为什么 std::function 可以持有 capture-lambda?

(2) as both std::function and function pointers are callable , what's the core difference that makes std::function able to hold capture-lambda, while function pointer cannot? (2) as both std::function and function pointers are callable , what's the core difference that makes std::function able to hold capture-lambda, while function pointer cannot?

Any detailed explanation on language design for this?关于语言设计的任何详细解释?

Why can a function pointer not hold a lambda with a capture: because a Lambda is NOT a function,it's an object! Why can a function pointer not hold a lambda with a capture: because a Lambda is NOT a function,it's an object!

Why can a lambda without a capture be converted to a function pointer?为什么没有捕获的 lambda 可以转换为 function 指针?

A Lambda is just an ordinairy object (a piece of data) of a compiler generated class (with a unique classname that only the compiler knows) with a function-operator member (ie auto operator() (??? )) that the compiler defines for you with the parameter definitions (if any) you provide. Lambda 只是编译器生成的 class (具有只有编译器知道的唯一类名)的普通 object (一条数据)(具有编译器知道的唯一类名)(???)使用您提供的参数定义(如果有)为您定义。 The data-members of a lambda-object are defined by the capture-list and/or usage of variables of its enclosing scope. lambda 对象的数据成员由其封闭 scope 的捕获列表和/或变量的使用定义。

All non-static member functions when called on an object get a implicit hidden argument called this.在 object 上调用时,所有非静态成员函数都会得到一个名为 this 的隐式隐藏参数。 This is also the case when you 'call' the lambda.当您“调用”lambda 时也是如此。

Now,when you don't capture something,the lambda has no data (empty class) and the compiler doesn't have to generate an implicit this pointer for the call,which makes the function operator just like an ordinairy function and the compiler can convert it to function pointer. Now,when you don't capture something,the lambda has no data (empty class) and the compiler doesn't have to generate an implicit this pointer for the call,which makes the function operator just like an ordinairy function and the compiler can将其转换为 function 指针。 So it not the lambda that is converted to a function-pointer,it's the lambda's function-operator that is converted.因此,不是 lambda 被转换为函数指针,而是 lambda 的函数运算符被转换。

Why can std::function hold both: because it's a template and with templates and specializations you can do almost anything.为什么 std::function 可以两者兼得:因为它是一个模板,并且通过模板和专业化,您几乎可以做任何事情。

There's no reason not to implement it in std::function<> , so it's implemented.没有理由不在std::function<>中实现它,所以它已经实现了。

The reason a function pointer cannot hold a capture lambda is that the latter has a this pointer and there's no place to store that in the function pointer (well, unless you compile new code or assign it from a pool). function 指针无法保存捕获 lambda 的原因是后者有一个this指针,并且没有地方将其存储在 function 指针中,除非您编译新代码或从井池中分配它。 However, std::function<> can allocate arbitrary amount of space, amongst these, the this pointer.但是, std::function<>可以分配任意数量的空间,其中包括this指针。

You can understand this better if you try to implement a function returning function pointers for lambdas (which, when called, by specification should call the lambda).如果您尝试实现 function 返回 lambda 的 function 指针(在调用时,规范应该调用 lambda),您可以更好地理解这一点。

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

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