在lambda表达式中指定捕获变量的目的是什么?

时间:2013-08-28 19:36:06

标签: c++ c++11 lambda

我有这段代码:

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

但我可以省略我并且只使用:

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

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

5 个答案:

答案 0 :(得分:26)

&i表示仅捕获i作为参考,而&表示从示波器中捕获的所有变量。

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 ++为您提供对捕获变量的完全控制,以及要捕获的特定变量,如何捕获(通过值或引用)。

i=相同的推理:

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

希望有所帮助。

答案 1 :(得分: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

这就是更详细的语法可用的原因。

答案 2 :(得分:17)

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

答案 3 :(得分:11)

  

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

您可以指定是通过引用还是按值捕获值。使用[&]指定您希望通过引用捕获所有内容,但您也可以编写lambda:

[=, &i, &j]()

其中说按价值捕捉所有内容,除了通过引用捕获ij

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

答案 4 :(得分:4)

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

这实际上取决于具体情况。我认为lambda越复杂和/或包含范围越复杂,就越明白你所捕获的内容。

还有一个额外的点,那就是按价值混合捕捉并通过引用捕捉 - 你必须至少明确其中一个。例如:

int i, j, k;

auto f = [=, &i]() { /* code which can read i, j and k but can only modify i */ };