“通过移动捕获”不会阻止通过引用捕获

问题描述

当我写 [&,x](){ /* making use of x */ } 时,x 被值捕获。

当我写 [=,&x](){ /* making use of x */ } 时,x 被引用捕获。

如果我尝试编写 [&x,x](){ … },我会收到一条错误消息,告诉我 x 在捕获列表中只能出现一次。

然而,[&x,y = std::move(x)](){ /* making use of x and y */ }(); 编译正常,但出现分段错误

为什么代码甚至可以编译?为什么标准允许我通过引用捕获变量,并且我也在“通过移动捕获”初始化捕获中使用它?

解决方法

从编译器的角度来看,情况 [&x,y = std::move(x)](){ }; 是非常合法的,因为不同的标识符用于捕获。标准如下:

[expr.prim.lambda/capture-2]

忽略init-captures初始化器中的出现,标识符或thislambda-中不应出现多次捕获

[&i,a = i]{ };    // OK
[&i,a = std::move(i)]{ };    // OK

[&i,i]{ };       // error: i repeat
[&i,i = std::move(i)]{ };    // error: i repeated