按值可变的 lambda 捕获不适用于 const &?

lambda capture by value mutable doesn't work with const &?

本文关键字:适用于 不适用 const lambda      更新时间:2023-10-16

请考虑以下事项:

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( 进行测试,这是错误消息的来源。

[C++11: 5.1.2/14]: 如果实体是隐式捕获的并且捕获默认值=,或者如果使用不包含&的捕获显式捕获实体,则通过复制捕获实体。对于 copy 捕获的每个实体,将在闭包类型中声明一个未命名的非静态数据成员。未指定这些成员的声明顺序。如果实体不是对对象的引用,则此类数据成员的类型是相应捕获实体的类型,否则为引用的类型。[..]

lambda 中的value类型是 const int ,因为它是通过从const int&复制捕获的。

因此,即使 lambda 的调用运算符函数不是const(您将 lambda 标记为mutable(,实际的隐式成员valueconst int 类型并且不能改变。

坦率地说,这似乎很荒谬;我希望这条规则说引用的类型会失去const,因为它是一个副本。lambda 本身上是否存在 mutable 关键字(因此,生成的调用运算符函数上是否存在 const 关键字(应该是此处唯一的访问控制。

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

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

所以这段代码有效(并输出inside 2 outside 1(:

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

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

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

void test( const int &value )

如果我们做copyValue const

const int valueCopy = value;

然后第二个 lambda 将发生相同的错误。

相关文章: