Lambda 表达式

AI-摘要
小米里的大麦 GPT
AI初始化中...
介绍自己 🙈
生成本文简介 👋
推荐相关文章 📖
前往主页 🏠
前往爱发电购买
Lambda 表达式
小米里的大麦匿名函数 —— Lambda 表达式
1. 什么是匿名函数(Lambda 表达式)?
在 C++中,匿名函数通常指的是没有名称的函数,也叫做“lambda 表达式”。匿名函数可以在代码中定义并立即使用,常见于临时的、一次性使用的操作。对于类和对象来说,匿名函数常常用于定义类内部的行为或操作。Lambda 表达式的基本形式如下:
1 | [捕获列表](参数列表) -> 返回类型 { 函数体 } |
- 捕获列表:决定了 lambda 函数是否可以访问外部变量。
- 参数列表:与普通函数一样,lambda 函数也可以接收参数。
- 返回类型:指定 lambda 函数返回的类型(如果不指定,编译器会自动推断)。
- 函数体:包含函数的实际操作。
示例:
1 | auto add = [](int a, int b) -> int { |
这里,[] 是捕获列表,表示 lambda 函数没有捕获外部变量,int a, int b 是参数列表,-> int 表示返回类型,return a + b; 是函数体。
2. 参数列表 (...) —— 和普通函数的参数完全一致
() 里的参数就是传给 Lambda 的输入,和普通函数的参数规则 完全一样:
- 传值、传引用(
&)、传指针、自定义类型、甚至函数指针 / 类对象,都和普通函数一样。 - 目的也一样:想修改外部变量本身(不拷贝副本)就传引用(
&);想高效传递大对象也用引用;普通小变量传值即可。
传值(和普通函数一样,内部修改不影响外部):
1
auto add = [](int a, int b) { return a + b; };
传引用(内部修改会影响外部,速度快,不拷贝):
1
2
3
4
5auto increment = [](int& x) { x++; }; // 注意参数是 int&
// 测试:
int x = 5;
increment(x); // x 变成 6
std::cout << x << std::endl; // 输出 61
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
using namespace std;
int main()
{
int x = 10, y = 20;
auto lambda = [x, &y]() {
cout << "x = " << x << ", y = " << y << endl;
};
x = 50; // x 变了,lambda 内部不会受影响
y = 60; // y 变了,lambda 内部会看到最新的 y 值
lambda(); // 输出 x = 10, y = 60
return 0;
}传递一些特殊类型(指针/类对象等):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
struct Person
{
std::string name;
int age;
};
int main()
{
// 1. 传指针(和普通指针用法一样)
auto print_ptr = [](Person* p) {
std::cout << p->name << " " << p->age << std::endl;
};
// 2. 传自定义类对象(可以传值或引用)
auto get_age = [](const Person& p) { return p.age; }; // 传 const 引用更高效
Person p = { "Alice", 20 };
print_ptr(&p); // 输出 Alice 20
std::cout << get_age(p) << std::endl; // 输出 20
return 0;
}
简单说:() 里的参数怎么写,完全参照普通函数,不用额外记新规则。在上面的示例中,相信大家也发现了:代码中并没有明确指明返回类型,这是为什么呢?
3. 为什么可以省略 -> 返回类型?
日常使用中,90% 以上的 Lambda 表达式都可以省略
-> 返回类型,这也是大家更常用简化写法的原因。
C++11 及以上标准中,Lambda 表达式的返回类型可以 自动推导,规则如下:当函数体中只有一条 return 语句时,编译器会根据返回值的类型自动推断 Lambda 的返回类型。此时,-> 返回类型 可以完全省略。 所以就有了:
1 | // 省略返回类型,编译器自动推导为 int |
什么时候必须显式写 -> 返回类型?
当 Lambda 函数体中存在 多个 return 语句,且返回值类型可能不一致时,必须显式指定返回类型。
1 | // 错误:多个 return 语句,类型可能不同,编译器无法自动推导 |
4. 捕获列表 [] —— 控制 Lambda 能否访问外部变量,以及怎么访问
这是 Lambda 最特殊的部分。[] 里的内容决定了 Lambda 能否使用 定义它的作用域中的变量(比如 main 函数里的局部变量),以及是 “拷贝用” 还是 “直接操作原变量”。
1. 常见捕获方式
| 捕获列表 | 含义 | 通俗理解 |
|---|---|---|
[] | 不捕获任何外部变量 | Lambda 里用不了外面的变量 |
[x] | 传值 捕获 x | 拷贝一份 x 到 Lambda 里,内部改的是副本,不影响外面的 x |
[&x] | 传引用 捕获 x | 直接用外面的 x,内部修改会影响外部(速度快,不拷贝) |
[=] | 传值 捕获 所有 用到的外部变量 | 只要 Lambda 里用了某个外部变量,就自动拷贝一份(省心但可能低效) |
[&] | 传引用 捕获 所有 用到的外部变量 | 只要 Lambda 里用了某个外部变量,就直接用原变量(高效,适合修改外部变量) |
[=, &x] | 大部分变量传值,但 x 传引用 | 混合模式:默认传值,单独指定 x 传引用 |
[&, x] | 大部分变量传引用,但 x 传值 | 混合模式:默认传引用,单独指定 x 传值 |
代码示例:
1 |
|
1 |
|
2. mutable 关键字
1 | int x = 10; |
5. 什么时候用 Lambda?
简单说:临时需要一个小函数,不想费劲定义普通函数时,比如:
1 |
|
评论
匿名评论隐私政策
✅ 你无需删除空行,直接评论以获取最佳展示效果














