短的例子:

#include <iostream>

int main()
{
    int n;
    [&](){n = 10;}();             // OK
    [=]() mutable {n = 20;}();    // OK
    // [=](){n = 10;}();          // Error: a by-value capture cannot be modified in a non-mutable lambda
    std::cout << n << "\n";       // "10"
}

问题是:为什么我们需要mutable关键字?它与传统的参数传递到命名函数有很大不同。背后的原理是什么?

在我的印象中,按值捕获的全部意义在于允许用户更改临时对象——否则我几乎总是使用按引用捕获更好,不是吗?

有什么启示吗?

(顺便说一下,我用的是MSVC2010。这应该是标准的)


当前回答

你必须理解捕获的意思!这是捕获而不是参数传递!让我们看一些代码示例:

int main()
{
    using namespace std;
    int x = 5;
    int y;
    auto lamb = [x]() {return x + 5; };

    y= lamb();
    cout << y<<","<< x << endl; //outputs 10,5
    x = 20;
    y = lamb();
    cout << y << "," << x << endl; //output 10,20

}

正如你所看到的,即使x被更改为20,仍然返回10 (x在lambda中仍然是5) 在lambda内部更改x意味着在每次调用中更改lambda本身(lambda在每次调用中都发生突变)。为了加强正确性,标准引入了mutable关键字。通过将lambda指定为mutable,就意味着对lambda的每次调用都可能导致lambda本身的更改。让我们看另一个例子:

int main()
{
    using namespace std;
    int x = 5;
    int y;
    auto lamb = [x]() mutable {return x++ + 5; };

    y= lamb();
    cout << y<<","<< x << endl; //outputs 10,5
    x = 20;
    y = lamb();
    cout << y << "," << x << endl; //outputs 11,20

}

上面的例子表明,通过使lambda可变,在lambda内部改变x会在每次调用时用一个新的x值“突变”lambda,而这个x值与主函数中x的实际值没有任何关系

其他回答

我的印象是 价值捕获的关键在于 允许用户更改临时 —否则,我几乎总是更好地使用引用捕获,而不是 我吗?

N不是暂时的。N是使用lambda表达式创建的lambda-function-对象的成员。默认的期望是,调用你的lambda不会修改它的状态,因此它是const,以防止你意外地修改n。

它需要mutable,因为默认情况下,函数对象每次调用都应该产生相同的结果。这就是面向对象的函数和使用全局变量的函数之间的区别。

You need to think what is the closure type of your Lambda function. Every time you declare a Lambda expression, the compiler creates a closure type, which is nothing less than an unnamed class declaration with attributes (environment where the Lambda expression where declared) and the function call ::operator() implemented. When you capture a variable using copy-by-value, the compiler will create a new const attribute in the closure type, so you can't change it inside the Lambda expression because it is a "read-only" attribute, that's the reason they call it a "closure", because in some way, you are closing your Lambda expression by copying the variables from upper scope into the Lambda scope. When you use the keyword mutable, the captured entity will became a non-const attribute of your closure type. This is what causes the changes done in the mutable variable captured by value, to not be propagated to upper scope, but keep inside the stateful Lambda. Always try to imagine the resulting closure type of your Lambda expression, that helped me a lot, and I hope it can help you too.

你必须理解捕获的意思!这是捕获而不是参数传递!让我们看一些代码示例:

int main()
{
    using namespace std;
    int x = 5;
    int y;
    auto lamb = [x]() {return x + 5; };

    y= lamb();
    cout << y<<","<< x << endl; //outputs 10,5
    x = 20;
    y = lamb();
    cout << y << "," << x << endl; //output 10,20

}

正如你所看到的,即使x被更改为20,仍然返回10 (x在lambda中仍然是5) 在lambda内部更改x意味着在每次调用中更改lambda本身(lambda在每次调用中都发生突变)。为了加强正确性,标准引入了mutable关键字。通过将lambda指定为mutable,就意味着对lambda的每次调用都可能导致lambda本身的更改。让我们看另一个例子:

int main()
{
    using namespace std;
    int x = 5;
    int y;
    auto lamb = [x]() mutable {return x++ + 5; };

    y= lamb();
    cout << y<<","<< x << endl; //outputs 10,5
    x = 20;
    y = lamb();
    cout << y << "," << x << endl; //outputs 11,20

}

上面的例子表明,通过使lambda可变,在lambda内部改变x会在每次调用时用一个新的x值“突变”lambda,而这个x值与主函数中x的实际值没有任何关系

现在有一个建议可以减轻lambda声明中对mutable的需求:n3424