当前位置: 首页 > 知识库问答 >
问题:

值可变的lambda捕获不适用于常量

宰父劲
2023-03-14

考虑以下几点:

void test( const int &value )
{
    auto testConstRefMutableCopy = [value] () mutable {
        value = 2; // compile error: Cannot assign to a variable captured by copy in a non-mutable lambda
    };

    int valueCopy = value;
    auto testCopyMutableCopy = [valueCopy] () mutable {
        valueCopy = 2; // compiles OK
    };
}

为什么第一个版本是编译错误,当我已经声明lambda是可变的,并通过值捕获value(我认为是它的副本)?

使用clang(x86_64-apple-darwin14.3.0)和Visual C(vc120)进行测试,这是错误消息的来源。

共有2个答案

顾俊楚
2023-03-14

mutable允许lambda修改copy捕获的非常量参数的副本,但不允许对const参数进行修改。

所以这段代码工作(并输出内2外1):

int a = 1;
[a]() mutable {
    a = 2; // compiles OK
    cout << "inside " << a << "\n";
}();
cout << " outside " << a << "\n";

但是如果我们省略了mutable,或者生成了const int,编译器就会给出一个错误。

在我们的例子中,第一个lambda给出了一个错误,因为valueconst

void test( const int &value )

如果我们使复制Valueconst

const int valueCopy = value;

第二个lambda也会出现同样的错误。

严昀
2023-03-14

[C11: 5.1.2/14]:如果实体被隐式捕获,并且捕获默认值为=< /code>,或者如果它被显式捕获,并且捕获不包括

lambda中值的类型是常量int,因为它是通过从常量int复制来捕获的

因此,即使lambda的调用操作符函数不是const(您标记了lambdamutable),实际的隐式成员value的类型是const int,并且不能被变异。

坦率地说,这看起来很荒谬;我希望这条规则说引用的类型失去了constness,因为它是一个副本。lambda本身是否存在mutable关键字(以及生成的调用操作符函数是否存在const关键字)应该是这里唯一的权限改造。

在C 14中,您可以通过捕获[value=value]来解决这个问题,它使用与auto相同的规则,从而删除const。C很棒,不是吗?

 类似资料:
  • 如问题所示,值可变的lambda捕获不适用于常量 但是为什么对不可变的lambda也这样做呢?在不可变lambda中,声明为,因此它无论如何都不能修改捕获的值。 当我们移动lambda时,这种情况的坏后果就会发生,例如,当我们将lambda包装在一个中时。 请参见以下两个示例: 我们得到以下编译器生成的lambda类: 程序打印以下内容(使用gcc或clang): 在第一个示例中,至少复制了三次值

  • 我想使用Boost.Range和带有init-capture的C 1y lambdas来计算两个向量的元素差异。减去一个向量的固定(即第一个)元素的更简单情况是有效的。但是,当我尝试通过在第二个范围上增加迭代器(并使lambda可变)来计算“矢量化差异”时,我得到一个编译器错误。示例代码(请注意,我没有使用通用的 lambda,因此 g 4.8 和 Clang SVN 都可以解析此代码): 活生生

  • 这个问题与前一个问题相关,在前一个问题中,我们注意到init捕获lambdas与Boost的范围和迭代器不兼容,因为一些相当模糊且嵌套很深的故障可能很难通过破解Boost来解决。射程源。 接受的答案建议将lambda存储在对象中。为了避免潜在的函数调用开销,我编写了两个函数对象,可以作为潜在的解决方法。它们在下面的代码中被称为和 不使用和编译行,并正确打印行的的实例。 然而,标准草案提到 5.1.

  • 我已经看过并尝试了几乎所有关于这个话题的其他帖子,但运气不好。 我使用的是python 3.6,所以我使用的是以下AMI

  • 无法在中包装流对象。 我试过这样: Eclipse开始抱怨在下划线,并建议它需要用try/catch包围

  • 我使用的OptaPlanner有两个规划变量,其中一个定义为nullable=true。遵循会议示例(为简单起见),假设Room可以为空,但Time不能为空。 我在非空的变量上定义了一个约束,但似乎只有当可空的变量不为空时,惩罚才起作用,否则会失败。 下面是我的代码片段: 在我的约束提供者类中,我定义了以下约束来确保一个人不能参加两个单独的会议: 当创建两个具有非空值的对象时,如果假设同一个人同时