我有这段代码:
int i = 0;
[&i](){i++;}();
但我可以省略我并且只使用:
[&](){i++;}();
指定&i
的目的是什么? (类似地=var
和=
)。它是否会影响编译时间或运行时性能?
答案 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]()
其中说按价值捕捉所有内容,除了通过引用捕获i
和j
。
在您的特定情况下,这没有用 - 您可以说通过引用捕获所有内容,编译器将确定您正在使用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 */ };