递归调用包装函数时 lambda 函数的内部工作

Inner working of lambda functions when wrapper function is called recursively

考虑以下代码:

int foo() {
    int lf = [/*captures*/]() {/*body*/};
    if(/*some condition*/) { return /*value*/; }
    foo();    //recursive call
}

现在,在这段代码中,每当递归调用函数 foo 时,fooactivation record 将被推入堆栈。我想知道的是,lambda 函数及其定义是否包含在记录中?嗯..this 没用

lambda 存储在 foo() 的局部变量中,所以是的。每次调用 foo() 都会实例化一个新的 lambda,直到 foo() 退出才会被销毁。

lambda 只是实现 operator() 的编译器定义类型的语法糖。因此,您的示例 大致 相当于:

struct functor{
    /*captures*/
    void operator()() const {/*body*/}
};

int foo() {
    functor lf{/*captures*/};
    if(/*some condition*/) { return /*value*/; }
    foo(); //recursive call
}

首先:

int lf = [/*captures*/]() {/*body*/};

是错误的代码,应该是

// case 1. lambda is automatic
auto lf = [/*captures*/]() {/*body*/}; // closure object

或(前提是 lambda returns 与 int 兼容)

// case 2. lambda is temporary
int lf = [/*captures*/]() {/*body*/} (); /* calling object created */

lambda 表达式是一个 shorthand 符号,用于创建具有唯一 class 的对象 (非常简单,您必须查看标准或语言参考以获取完整描述):

class Closure {
    /* members storing captured values or references */ 
public:
    return-type  operator( /* argument list*/ ) { /*body*/ };
}

在第一种情况下,lambda 将存储在堆栈中,在第二种情况下,它是一个临时对象。

所以带有捕获列表的 lambda 会存储这样的对象,即所有捕获的值正好在您指示它存储 lambda 对象的位置,在您的情况下它是自动存储(所谓的 "stack")。使用无捕获 lambda 与声明一个函数并使用指向它的指针没有什么不同,没有与之关联的存储并且它可以转换为函数指针。