【问题标题】:When does a variable copy be released in lambda function?什么时候在 lambda 函数中释放变量副本?
【发布时间】:2021-10-09 04:04:51
【问题描述】:

如下例,我定义了 2 个变量 x 和 y。当我两次调用 lambda 函数时,它似乎不会破坏副本。来自11.14 — Lambda captures | Learn C++ - Learn C++,它说:

因为捕获的变量是 lambda 对象的成员,所以它们的值会在对 lambda 的多次调用中保持不变!

C++ 如何管理 lambda 函数的内存?

int main() {
    int x = 1;
    static int y = 1;
    auto fun = [=]() mutable{
        x++;
        y++;
        cout<<"Inside:\t\t";
        cout<<"x:"<<x<<"\t"<<"y:"<<y<<endl;
    };

    for (int i = 0; i<2; i++) {
        fun();
        cout<<"Outside:\t";
        cout<<"x:"<<x<<"\t"<<"y:"<<y<<endl<<endl;
    }
}

输出:

Inside:         x:2     y:2
Outside:        x:1     y:2

Inside:         x:3     y:3
Outside:        x:1     y:3

【问题讨论】:

    标签: c++ memory lambda


    【解决方案1】:

    它将它存储在对象本身中。下面是另一种思考 lambda 的方法。这“有点”相当于编译器生成的内容,是的,我正在稍微改变范围,我知道,但这对于 C++ 的初学者来说可能更清楚。

    static int y = 1; // Moved this out from main
    class my_lambda{
    public:
    my_lambda(int x) : _x(x) {}
    ~my_lambda() = default;
    void operator()()
    {
      _x++;
      y++;
      cout<<"Inside:\t\t";
      cout<<"_x:"<<_x<<"\t"<<"y:"<<y<<endl;
    }
    
    private:
    int _x;
    };
    
    int main() {
        int x = 1;
        my_lambda fun{x}; // "Captures" x
    
        for (int i = 0; i<2; i++) {
            fun();
            cout<<"Outside:\t";
            cout<<"x:"<<x<<"\t"<<"y:"<<y<<endl<<endl;
        }
    }
    

    正如您所希望看到的,我制作的“假 lambda”类与您的实际 lambda 所做的相同。它“捕获”x 作为其构造函数的一部分并将其复制到内部存储,我称之为_x。并且 y 只是在它的范围内,尽管我移至 global 以位于类声明之上。

    我正在重载() 运算符以创建一个可调用的类,这在某些情况下是很正常的事情。如果您想了解更多信息,请联系运营商overloading

    所以这就是 lambdas 的工作方式。他们将您的身体放入所生成对象的operator() 中,捕获的任何内容都是对象的变量之一,如果以这种方式捕获,则带有实际对象(如果按值)或引用。

    直接回答您的问题:当fun 超出范围时,它会在 lambda 和我的情况下被释放。

    【讨论】:

    • 谢谢凯文!我很感激。你用类对象来解释这个概念真是太棒了。非常清晰直观。
    • 很高兴这对您有所帮助。我发现它有助于编译器尝试将其解构为“如果我必须自己实现它,我将如何做到这一点?”的许多“魔法”。这不是 100% 有效,但经常以简单的方式重写编译器超优化的东西可以帮助您了解正在发生的事情。以上是我主要“概念化” lambdas 的方式。它并不完美,而且在效率上绝对不及编译器所做的那样,但它可以理解变量生命周期等问题,这是您问题的重点。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-25
    • 2018-11-12
    相关资源
    最近更新 更多