【问题标题】:Lambda capture by value and the "mutable" keywordLambda 按值捕获和“可变”关键字
【发布时间】:2017-06-22 17:25:23
【问题描述】:

在 lambdas 中需要关键字 mutable,这是非常混乱的根源。

考虑代码:

int x = 10;

function<void()> lambda = [=]() mutable {x++; cout << "Inside lambda: x = " << x << "\n";};

cout << "Before lambda: x = " << x << "\n";
lambda();
cout << "After  lambda: x = " << x << "\n\n";

输出:

Before lambda: x = 10
Inside lambda: x = 11
After  lambda: x = 10

正如我们所见,变量 x 在 lambda 之后保持不变,因此没有副作用。

但是,如果我们“忘记”关键字 mutable,就会出现错误。

作为在 C++ 中按值传递默认值的参数,对我来说需要 mutable 关键字没有任何意义。

有人可以编写(即使是伪代码)编译器生成的类来代替 lambda 吗?

谢谢

【问题讨论】:

标签: c++ lambda


【解决方案1】:

here 所述,mutable 说明符允许 lambda 修改由复制捕获的参数并调用它们的非常量成员函数。它不会影响通过引用捕获的变量。

有人可以编写(即使是伪代码)编译器生成的类来代替 lambda 吗?

给出一般情况并不容易,但我们可以定义一些对您的具体情况有效的内容。
生成的类可能如下所示:

struct Lambda {
    void operator()() { x++; }
    int x{10};
};

如果删除mutable 说明符,则函数运算符定义为const

struct Lambda {
    void operator()() const { x++; }
    int x{10};
};

为简单起见,我已使用给定值 (10) 初始化 x 并将其公开,但它显然是通过使用从周围上下文捕获的变量复制初始化的,并且无法从函数运算符外部访问。
它的类型也是从用于初始化它的变量中推断出来的,就像你这样做一样:

auto lambda_x = x;

更多详情请参阅here

【讨论】:

    【解决方案2】:
    class Lambda
    {
    public:
       Lambda(const Lambda&);
       ~Lambda();
    
       // the main functor operator, const when lambda not mutable
       R operator()(Args args) const;
    
       // Only present for non-capture lambda         
       operator PlainCFunctionType () const; 
    
       // Only present for non-capture  lambda         
       PlainCFunctionType operator+() const;
    private:
       // Gets called when lambda created, but you can't call it yourself
       Lambda(Captures captures...); 
    
       Captures captures;
    };
    

    【讨论】:

      【解决方案3】:

      您并没有真正以面向对象的方式编写代码,但无论如何。 通常由 [=] 添加的外部变量是 const 值。通过添加 mutable 关键字,您可以创建它们的本地可修改副本。 您可以使用 [&] 来通过引用进行捕获。

      【讨论】:

      • 使用 [&] 改变 lambda 后的变量值。在我的代码中,捕获是按值进行的。
      猜你喜欢
      • 2020-02-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-06-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多