一. lambda表达式语法
语法格式:
[capture-list] (parameters) mutable -> return-type { statement}
说明:
[capture-list]
:捕捉列表,捕捉列表能够捕捉上下文中的变量供lambda函数使用。
捕捉列表在lambda函数的开始位置,编译器根据[]来判断接下来的代码是否为lambda函数(parameters)
:参数列表,与普通函数的参数列表一致。如果不需要传参,则可连同()一起省略mutable
:修饰符,可以取消以值传递的变量的常量性。使用该修饰符时,参数列表不可省略(即使参数为空)->retrun-type
:返回值类型,没有返回值时可省略,返回值类型明确情况下,也可省略,由编译器对返回类型进行推导{statement}
:函数体
tips:
在lambda函数中,参数列表、返回值类型和mutable修饰符都是可选部分。
最简单的lambda表达式:
[]{};//该表达式没有任何意义
二. 捕捉列表
tips:
对于而对于全局变量、静态变量、全局函数等全局作用域下的成员,我们无需通过捕获列表就可直接使用
int year = 2023;
static int month = 2;
string time()
{
return "3:45";
}
int main()
{
static int day = 18;
[]{
printf("%d/%d/%d-", year, month, day);
cout << time() << endl;
}();
return 0;
}
通过
()
来调用lambda函数—>[]{…}();
[]
:不捕获任何外部变量[var1, var2, ..]
: 表示传值方式捕捉变量var1,var2,…[=]
:表示值传递方式捕捉所有父作用域中的所有变量(包括this)[&var1, &var2, ..]
:表示引用传递捕捉变量var1, var2, …[&]
:表示引用传递捕捉父作用域的所有变量(包括this)
tips:
a. 能捕捉的变量必须是在该lambda函数声明前声明的变量**
b. 父作用域:指{}
包含lambda函数的块作用域
c. 语法上捕捉列表可以由多个捕捉项构成,以,
分隔
[=, &a, &b]:以引用传递方式捕捉变量a和b,值传递方式捕捉其他所有变量
d. 不允许变量重复传递,也不允许=或&的使用在单个变量后,否则会导致编译错误
mutable修饰符
默认情况下,通过捕捉列表以值传递捕捉的变量是具有const 常量性的。增加mutable
可以取消以值传递的变量的常量性。
error C3491: “a”: 无法在非可变 lambda 中修改通过复制捕获
int main()
{
int a = 1, b = 2, c = 3;
//使用mutable需要带上()
auto fun1 = [=]()mutable {
a = 100;
return a + b + c;
};
cout << fun1() << endl;
return 0;
}
三.原理
class Rate
{
public:
Rate(double rate) : _rate(rate)
{}
double operator()(double money, int year)
{
return money * _rate * year;
}
private:
double _rate;
};
int main()
{
// 函数对象
double rate = 0.49;
Rate r1(rate);
r1(10000, 2);
// lamber
auto r2 = [=](double monty, int year)->double {return monty * rate * year;
};
r2(10000, 2);
return 0;
}
实际在底层编译器对于lambda表达式的处理方式,完全就是按照函数对象的方式处理的,即:如
果定义了一个lambda表达式,编译器会自动生成一个类,在该类中重载了operator() 。
🦀🦀观看~~