C++Lambda表达式
·
定义
[capture](parameters) mutable noexcept -> return_type { body }
| 部分 | 说明 | 是否可选 |
|---|---|---|
[capture] |
捕获列表:指定如何访问外部变量 | ❌ 必需(可为空 []) |
(parameters) |
参数列表(类似函数) | ✅ 可省略(无参时) |
| mutable | 允许修改按值捕获的变量副本(不影响外部变量) | ✅ 可省略 |
| noexcept | 用于指定是否抛出异常,如果指定了noexcept,内部需要做好try-catch处理;否则该抛异常还是会抛异常 | ✅ 可省略 |
-> return_type |
返回类型(通常可自动推导) | ✅ 可省略 |
{ body } |
函数体 | ❌ 必需 |
#include <iostream>
#include <string>
using namespace std;
int main()
{
int a = 10, b = 20;
// 外部变量用不着,但是也需要写[]
// auto func1 = [](int x, int y) -> int { return x + y; };
auto func1 = [](int x, int y) { return x + y; };
int c = func1(a, b);
cout << "result=" << c << endl;
// 参数列表用不着,可以省略()
// auto func2 = []() -> string { return "hello world"; };
auto func2 = [] { return "hello world"; };
cout << "result=" << func2() << endl;
// mutable修饰
auto func3 = [a, b]() mutable {
cout << "before内部a=" << a << " ,b=" << b << endl;
b = 200;
cout << "after内部a=" << a << " ,b=" << b << endl;
};
func3();
cout << "外部a=" << a << " ,b=" << b << endl;
}
捕获列表
捕获列表决定 Lambda 如何访问外部作用域的变量
1、按值捕获
好处就是外面修改了,里面的值不会变
int main()
{
int a = 10;
auto func1 = [a]() {
cout << "内部a=" << a << endl;
// 不可修改,编译不过
// a = 100;
};
// 外部修改
a = 100;
func1();
cout << "外部a=" << a << endl;
}
2、按引用捕获
传引用,内部、外部都可以修改,一变全变
int main()
{
int a = 10;
auto func1 = [&a]() {
cout << "内部修改前a=" << a << endl;
// 内部修改
a = 100;
cout << "内部修改后a=" << a << endl;
};
// 外部修改
//a = 100;
func1();
cout << "外部a=" << a << endl;
}
3、隐式捕获
[=]:默认按值捕获所有用到的外部变量[&]:默认按引用捕获所有用到的外部变量
好处就是不用一个一个写参数了,默认全部参数一起带过去
按值所有
int main()
{
int a = 10, b = 20;
auto func1 = [=]() {
cout << "内部a=" << a << " ,b=" << b << endl;
};
// 外部修改
a = 100;
func1();
cout << "外部a=" << a << " ,b=" << b << endl;
}
按引用所有
int main()
{
int a = 10, b = 20;
auto func1 = [&]() {
cout << "before内部a=" << a << " ,b=" << b << endl;
b = 200;
cout << "after内部a=" << a << " ,b=" << b << endl;
};
// 外部修改
a = 100;
func1();
cout << "外部a=" << a << " ,b=" << b << endl;
}
4、混合捕获
[=, x]不能在默认按值后显式按值捕获[&, &x]不能在默认按引用后显式按引用捕获
int main()
{
int a = 10, b = 20;
auto func1 = [a, &b]() {
cout << "before内部a=" << a << " ,b=" << b << endl;
b = 200;
cout << "after内部a=" << a << " ,b=" << b << endl;
};
// 外部修改
a = 100;
func1();
cout << "外部a=" << a << " ,b=" << b << endl;
}
Lambda的本质
Lambda 表达式会被编译器转换为唯一的匿名类(闭包类型),重载了
operator()
// Lambda
auto f = [x](int y) { return x + y; };
// 等价于
class __lambda_xyz123 {
int x;
public:
__lambda_xyz123(int x) : x(x) {}
auto operator()(int y) const { return x + y; }
};
其他特性
支持泛型
int main()
{
int a = 10, b = 20;
auto fun1 = [](auto a, auto b) { return a + b; };
cout << "a+b= =" << fun1(a, b) << endl;
cout << "a+b= =" << fun1(1.23, 3.45) << endl;
}
支持模板
int main()
{
int a = 10, b = 20;
auto fun1 = []<typename T>(T x, T y) { return x * y; };
cout << "a+b= =" << fun1(a, b) << endl;
cout << "a+b= =" << fun1(1.23, 3.45) << endl;
}
泛型约束
int main()
{
int a = 10, b = 20;
auto fun1 = []<std::integral T>(T x, T y) { return x * y; };
cout << "a+b= =" << fun1(a, b) << endl;
// 这个数据类型不满足约束
//cout << "a+b= =" << fun1(1.23, 3.45) << endl;
// short -> int能隐式转换,满足约束
short c = 11, d = 22;
cout << "c+d= =" << fun1(c, d) << endl;
// long -> int不能隐式转换,不满足约束
long e = 11, fd = 22;
//cout << "e+f= =" << fun1(e, f) << endl;
}
所有评论(0)