我有这段代码:
void function1(char c, bool b){
auto get_allowed = [&](int x){
if(b){
.... some code...
}
...some code...
}
get_allowed(0);
...other_code...
}
在这种情况下我可以在lambda函数中使用b ??
我的意思是,将该参数添加到lambda函数的签名中是相同的,例如:
void function1(char c, bool b){
auto get_allowed = [&](int x,bool b){
if(b){
.... some code...
}
...some code...
}
get_allowed(0, false);
...other_code...
}
要澄清,区别在于:
auto get_allowed = [&](int x){
get_allowed(0);
VS
auto get_allowed = [&](int x,bool b){
get_allowed(0, false);
其中b是函数function1的参数。
答案 0 :(得分:2)
在您的示例中,两个版本的lambda的效果大致相同。但是,捕获的参数与“正常”参数之间存在显着差异。
以下是如何创建lambda:
[ capture-list ] ( params ) { body }
capture-list
可以让您访问lambda周围范围内的变量。有一些不同的捕获模式:
[&]
通过引用捕获周围范围内的所有局部变量(例如,示例中的b
和c
)[&b]
仅通过引用捕获b
,您可以根据需要添加任意数量的命名变量(逗号分隔)[=]
通过值捕获周围范围内的所有局部变量(换句话说:您的lambda包含这些变量的副本)[b]
仅通过副本b
[b, &c]
您可以混合使用复制和参考捕获您应该问问自己:这些捕获的内容是什么?
嗯,它定义了一个闭包,一个上下文,每次使用lambda时都是 。在许多情况下,在函数之上添加的那种状态非常有用。
一个例子:您要在集合的每个元素上映射lambda:
std::vector<int> numbers = {1, 2, 3, 4, 5};
int sum = 0;
std::for_each(std::begin(numbers), std::end(numbers),
[&sum](int n){ sum += n; });
在这里,我们使用通过引用捕获的变量来存储(和更新)向量中所有数字的总和。
花点时间思考这个例子,做一些你自己的实验,这就是关于lambdas的所有知识。 :)
答案 1 :(得分:1)
在第一个示例中,get_allowed
是一个参数的函数,其中隐式捕获b
(因为您使用[&]
捕获)。
在第二个中,get_allowed
是两个参数的函数,其中b
显式传递给get_allowed
而不是从周围函数中获取。
在这个例子中,lambda是不必要的,因此差异有点学术性。
答案 2 :(得分:1)
[&]
捕获列表确保lambda定义范围内的变量可以在lambda函数的主体中通过引用使用。
所以是的:在第一个片段中,b
在lambda中可用(只是不要忘记半列来结束函数赋值)。您甚至可以更改其值(在b
中影响get_allowed()
会更改b
的参数function1()
的值,因为它是通过引用捕获的)!
在第二个代码段中,您将b
作为参数传递给值。这工作方式不同。 b是通过值传递的参数的名称,它与封闭范围的b无关。
补充说明
注意:如果你的lambda在定义它的范围内存活(例如,如果你从function1()
返回lambda或存储get_allowed
的值),你可能会遇到捕获问题引用 ;稍后在另一个上下文中调用lambda可以引用不再存在的变量(悬空引用)。
如果您更喜欢松散耦合,您可以考虑使用[=]
捕获列表:它具有类似的效果,但捕获的变量按值传递(即没有意外修改也没有悬挂引用)。这使得lambda更加独立于创建它的上下文。
答案 3 :(得分:1)