简体   繁体   English

c ++ lambda按值捕获

[英]c++ lambda capture by value

I am reading through the C++ lambda section in chapter 3 of this book and the following code confuses me: 我正在阅读本书第3章中的C ++ lambda部分,以下代码让我困惑:

int x = 0;
int y = 42;
auto qqq = [x, &y] {
    std::cout << "x: " << x << std::endl;
    std::cout << "y: " << y << std::endl;
    ++y;
};
x = y = 77;
qqq();
qqq();
std::cout << "final y: " << y << std::endl;

This code prints out: 这段代码打印出来:

x: 0
y: 77
x: 0
y: 78
final y: 79

Why does qqq() not register that x has changed to 77? 为什么qqq()没有注册x已经改为77? It was stated that passing by value means we can read but not modify data readable where the lambda was defined. 据说,通过值传递意味着我们可以读取但不能修改定义lambda的数据。 Does that mean we can't see changes after it's definition? 这是否意味着我们在定义后无法看到变化?

That's because the variable is captured by value (ie copied) only once, when you define the lambda. 这是因为当你定义lambda时,变量只被值(即复制)捕获一次。 It's not "updated" as you may believe. 它可能不会像您所认为的那样“更新”。 The code is roughly equivalent to: 代码大致相当于:

#include <iostream>

int x = 0;
struct Lambda
{
    int _internal_x; // this is used to "capture" x ONLY ONCE
    Lambda(): _internal_x(x) {} // we "capture" it at construction, no updates after
    void operator()() const
    {
        std::cout << _internal_x << std::endl;
    }
} qqq; 

int main()
{
    qqq(); 
    x = 77; // this has no effect on the internal state of the lambda
    qqq();
}

Live on Coliru 住在Coliru

By binding a variable by value to a lambda closure, you're effectively copying the value of the variable into a separate variable that is found inside the lambda object. 通过将值变量绑定到lambda闭包,您可以有效地将变量的值复制到lambda对象中的单独变量中。 Likewise, by binding a variable by reference, you're making such an internal variable to be a reference to the original variable instead, thus being able to "see changes" on the original variable. 同样,通过引用绑定变量,您将使这样的内部变量成为对原始变量的引用,从而能够“看到原始变量的变化”。

Look at it like this. 像这样看待它。 The following code... 以下代码......

#include <iostream>

int main()
{
    int x = 0;
    int y = 42;
    auto qqq = [x, &y] {
        std::cout << "x: " << x << std::endl;
        std::cout << "y: " << y << std::endl;
        ++y;
    };
    x = y = 77;
    qqq();
    qqq();
    std::cout << "final y: " << y << std::endl;
}

Is (kind of, but not exactly) syntactic sugar for... 是(种类,但不完全)语法糖...

#include <iostream>

class MyLambda
{
    private:
        int x;
        int& y;

    public:
        MyLambda(int x, int& y) : x(x), y(y) {}

        void operator()()
        {
            std::cout << "x: " << x << std::endl;
            std::cout << "y: " << y << std::endl;
            ++y;
        }
};

int main()
{
    int x = 0;
    int y = 42;
    MyLambda qqq = MyLambda(x, y);
    x = y = 77;
    qqq();
    qqq();
    std::cout << "final y: " << y << std::endl;
}

With the exception of the special lambda syntax and the fact that you can't reference the lambda's type directly. 除了特殊的lambda语法和你不能直接引用lambda类型的事实。 By comparing the former with the later code, you should be able to clear out your understanding of closures. 通过将前者与后面的代码进行比较,您应该能够清除对闭包的理解。

The lambda uses the value at the time the lambda is defined (it makes a copy), not at the time it is invoked. lambda使用lambda定义时的值(它创建一个副本),而不是在调用它时。

This might help: How are Lambda Closures Implemented? 这可能有所帮助: Lambda Closures如何实现?

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

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