lambda 表达式定义了一个匿名函数,并且可以捕获一定范围内的变量。
[捕获列表] (参数列表) 选项 -> 返回值 { lambda函数体 };
mutable
,用于在使用=
捕获时仍能修改捕获变量的值{x1,x2,...}
这种需要手动指明具体的返回值类型)一个完整的lambda表达式示例:
int a = 2;
auto fun = [=](int b) -> int { return a + b + 1; };
std::cout << fun(3) << std::endl; // 输出: 6
捕获的范围是上一级作用域。
[]
不捕获任何变量。[&]
捕获外部作用域中所有变量,并作为引用在函数体中使用(按引用捕获)。[=]
捕获外部作用域中所有变量,并作为副本在函数体中使用(按值捕获)。[=, &foo]
按值捕获外部作用域中所有变量,并按引用捕获 foo 变量。[&, foo]
按引用捕获外部作用域中所有变量,并按值捕获 foo 变量。[bar]
按值捕获 bar 变量,同时不捕获其他变量。[this]
捕获当前类中的 this
指针,让 lambda 表达式拥有和当前类成员函数同样的访问权限。如果已经使用了 &
或者 =
,就默认添加此选项。捕获 this
的目的是可以在 lamda 中使用当前类的成员函数和成员变量。注意:
mutable
选项,或者干脆按引用捕获。lambda 表达式可以说是就地定义仿函数闭包的“语法糖”。
编译器会把我们写的lambda表达式翻译成一个类,并在类中重载 operator()
。
示例:
(1)按值捕获
写了一个lambda表达式:
int x = 1; int y = 2;
auto plus = [=] (int a, int b) -> int { return x + y + a + b; };
int c = plus(1, 2);
那么编译器的翻译结果:
class LambdaClass {
public:
LambdaClass(int xx, int yy)
: x(xx), y(yy) {}
int operator () (int a, int b) const {
return x + y + a + b;
}
private:
const int x;
const int y;
};
int x = 1; int y = 2;
LambdaClass plus(x, y);
int c = plus(1, 2);
(2)按引用捕获
写了一个lambda表达式:
int x = 1; int y = 2;
auto plus = [&] (int a, int b) -> int { x++; return x + y + a + b; };
int c = plus(1, 2);
那么编译器的翻译结果:
class LambdaClass {
public:
LambdaClass(int& xx, int& yy)
: x(xx), y(yy) {}
int operator () (int a, int b) {
x++;
return x + y + a + b;
}
private:
int &x;
int &y;
};
int x = 1; int y = 2;
LambdaClass plus(x, y);
int c = plus(1, 2);
于是可以发现:捕获列表捕获住的任何外部变量,最终均会变为闭包类型的成员变量。
const
修饰operator()
函数是const
修饰的常函数,不能修改成员变量的值,因此加上mutable
选项后就能修改按值捕获的变量的值了。operator()
函数没有const
修饰针对上面的集中情况,lambda的各个成分和类的各个成分对应起来如下:
捕获列表,对应LambdaClass类的private成员。其中按值捕获的变量修饰为const
成员变量,按引用捕获的就是普通的成员变量。
参数列表,对应LambdaClass类的成员函数的operator()的形参列表
mutable,对应 LambdaClass类成员函数 operator() 的const属性 ,但是只有在捕获列表捕获的参数不含有引用捕获的情况下才会生效,因为捕获列表只要包含引用捕获,那operator()函数就一定是非const函数。
返回类型,对应 LambdaClass类成员函数 operator() 的返回类型
**函数体,**对应 LambdaClass类成员函数 operator() 的函数体。
引用捕获和值捕获不同的一点就是,对应的成员是否为引用类型。
参考:
C++ Lambda表达式的完整介绍 - 知乎 (zhihu.com)
parallel processing - lambda expression error: expression must be a modifiable lvalue - Stack Overflow