28

我有这个代码:

int i = 0;
[&i](){i++;}();

但我可以省略 i 并使用:

[&](){i++;}();

指定的目的是&i什么?(同样=var=)。它是否影响编译时间或运行时性能?

4

5 回答 5

26

&ii表示作为参考被捕获,而&表示在 lambda 中使用的所有变量都是从作用域中捕获的。

int i = 0, j = 10;

[&i]{ i++; j++;}(); //error: j is not captured by reference

[&]{ i++; j++;}(); //ok: both variables are captured by reference

&i方法由语言提供以限制捕获的变量的数量。C++ 让您可以完全控制捕获的变量,例如要捕获哪些特定变量、如何捕获(按值或引用)。

iand的推理相同=

int i = 0, j = 10;

[i]{ i++; j++;}(); //error: j is not captured (only i is captured by value)

[=]{ i++; j++;}(); //ok: both variables are captured by value

//more
[&i, j]{ i++; j++;}(); //ok: captured i by reference, j by value

希望有帮助。

于 2013-08-28T19:37:50.963 回答
21

有时您可能希望以不同的方式捕获不同的变量:

std::vector<int> v { 7, 8, 9, 10, 11 };
int n = 3;

//Capture v by reference and n by value:
auto getNth = [&v, n](){ return v[n]; };

//Behavior:
n = 9999;
getNth(); //returns 10 - changing n didn't affect the lambda
v[3] = 42;
getNth(); //returns 42 - changing v did affect the lambda

这就是为什么可以使用更详细的语法的原因。

于 2013-08-28T19:40:23.523 回答
18

此功能与性能无关,它与可读性和可维护性有关。当您使用一揽子捕获语法时[&][=]它会掩盖原始方法和 lambda 主体之间共享的状态。如果开发人员错误地假定未捕获值而确实捕获了值,这可能会导致方法中的维护问题。拥有一个捕获子句使得 lambda 所依赖的状态更加明确。

于 2013-08-28T19:37:56.160 回答
11

指定 &i 的目的是什么?(类似地 =var 和 =)。它是否影响编译时间或运行时性能?

您可以指定是按引用还是按值捕获值。Using[&]指定您要通过引用捕获所有内容,但您也可以编写 lambda 来执行以下操作:

[=, &i, &j]()

这表示按价值捕获所有内容,捕获ij引用除外。

在您的特定情况下,这没有用-您可以只说通过引用捕获所有内容,编译器将确定您正在使用i并通过引用捕获它-但是当您处理要捕获的多个变量时,C++ 允许您控制如何单独捕获每个。

于 2013-08-28T19:39:25.733 回答
4

如果您列出要捕获的变量,那么您就明确了您想要的内容。如果你使用了你不想使用的东西(你没有捕获它),你会得到一个编译器错误。这可能是一件好事(你在实现中犯了一个真正的错误)或一件坏事(你只是忘记列出变量)。

这真的取决于特定的场景。我希望 lambda 越复杂和/或包含范围越复杂,就越能明确您捕获的内容。

还有一个额外的点,那就是混合按值捕获和按引用捕获 - 你必须至少在其中一个中明确。例子:

int i, j, k;

auto f = [=, &i]() { /* code which can read i, j and k but can only modify i */ };
于 2013-08-28T19:40:19.050 回答