使用c++参数lambda函数

Use parameter lambda function C++

本文关键字:函数 lambda 参数 c++ 使用      更新时间:2023-10-16

我有这段代码:

    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);

 auto get_allowed = [&](int x,bool b){
get_allowed(0, false);

,其中b是函数function1的形参。

在您的示例中,两个版本的lambda的效果大致相同。然而,捕获的参数与"正常"参数有一个显著的区别。

下面是创建lambda的方法:

[ capture-list ] ( params ) { body }

capture-list可以让您访问存在于lambda周围作用域中的变量。这里有一些不同的捕获模式:

  • [&]通过引用捕获周围作用域中的所有局部变量(即:bc(在您的示例中)
  • [&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; });

在这里,我们使用一个通过引用捕获的变量来存储(并更新)vector中所有数字的和。

花点时间来思考这个例子,做一些你自己的实验,这就是关于lambda的所有知识。:)

[&]捕获列表确保lambda定义周围作用域中的变量可以在lambda函数体中被引用使用。

所以是:在第一个代码片段中,b在lambda中是可用的(只是不要忘记结束函数赋值的半列)。你甚至可以改变它的值(影响get_allowed()中的b会改变function1()的参数b的值,因为它是通过引用捕获的)!

在第二个代码片段中,按值传递b作为参数。这是不同的。b是通过值传递的参数的名称,它与封闭作用域的b无关。

补充说明

注意:如果你的lambda在定义它的作用域中存活(例如,如果你从function1()返回lambda或存储get_allowed的值),你可能会遇到引用捕获的问题;稍后在另一个上下文中调用lambda可能会引用不再存在的变量(悬空引用)。

如果您更喜欢松散耦合,您可以考虑使用[=]捕获列表:它具有类似的效果,但捕获的变量是按值传递的(即没有意外修改或悬空引用)。这使得lambda更加独立于创建它的上下文。

在第一个示例中,get_allowed是一个参数函数,其中b被隐式捕获(因为您使用[&]捕获)。

在第二个函数中,get_allowed是一个有两个参数的函数,其中b显式传递给get_allowed,而不是从周围的函数中获取。

lambda在本例中是不必要的,所以两者的区别有点学术性。

在这种情况下,我可以在lambda函数内使用b吗??

是的,你可以在lambda中使用b

[&]通过引用捕获lambda主体中使用的所有自动变量

b被引用

捕获