C/C++内置库函数(7):lambda表达式
·
一、Lambda 的基础语法结构(构建的核心)
一个完整的 Lambda 表达式由 5 部分组成,其中捕获列表和函数体是必须的,其他部分可省略:
// 完整结构
[捕获列表](参数列表) mutable noexcept -> 返回类型 {
函数体
};
// 最简结构(只有捕获列表和函数体)
[] { 函数体 };
各部分详解
| 部分 | 说明 | 是否必须 |
|---|---|---|
[捕获列表] | 定义 Lambda 能访问的外部变量(值 / 引用) | ✅ 必须 |
(参数列表) | 和普通函数的参数列表一致 | ❌ 可省略(无参数时) |
mutable | 允许修改值捕获的外部变量 | ❌ 可省略 |
noexcept | 声明不抛出异常 | ❌ 可省略 |
-> 返回类型 | 显式指定返回类型(尾置返回类型) | ❌ 可省略(编译器自动推导) |
{ 函数体 } | 函数的具体实现逻辑 | ✅ 必须 |
二、核心:捕获列表的 5 种构建方式
捕获列表是 Lambda 最独特的部分,决定了 Lambda 能如何访问外部变量。
1. 空捕获 []
不捕获任何外部变量,Lambda 内部只能使用参数和全局变量。
#include <iostream>
using namespace std;
int main() {
int a = 10;
// 空捕获:不能访问 a
auto lambda = [] {
// cout << a << endl; // ❌ 编译错误:未捕获 a
cout << "Hello Lambda" << endl;
};
lambda();
return 0;
}
2. 值捕获 [变量名]
按值拷贝外部变量,Lambda 内部使用的是变量的副本,默认不能修改(除非加 mutable)。
#include <iostream>
using namespace std;
int main() {
int a = 10;
// 值捕获 a:内部用的是 a 的副本
auto lambda = [a] {
cout << "捕获的 a: " << a << endl;
// a = 20; // ❌ 编译错误:值捕获默认是 const 的
};
a = 100; // 修改外部 a,不影响 Lambda 内部的副本
lambda(); // 输出:捕获的 a: 10
return 0;
}
3. 引用捕获 [&变量名]
按引用捕获外部变量,Lambda 内部直接修改外部变量本身。
#include <iostream>
using namespace std;
int main() {
int a = 10;
// 引用捕获 a:内部直接修改外部 a
auto lambda = [&a] {
a = 20; // ✅ 可以修改外部变量
cout << "内部修改后的 a: " << a << endl;
};
lambda();
cout << "外部 a: " << a << endl; // 输出:外部 a: 20
return 0;
}
4. 隐式捕获(批量捕获)
不用逐个写变量名,让编译器自动推导需要捕获的变量:
[=]:所有外部变量都按值捕获;[&]:所有外部变量都按引用捕获;[=, &a]:大部分按值,只有a按引用;[&, a]:大部分按引用,只有a按值。
#include <iostream>
using namespace std;
int main() {
int a = 10, b = 20, c = 30;
// 隐式捕获:a按值,b和c按引用
auto lambda = [=, &b, &c] {
cout << "a (值): " << a << endl;
b = 200; // 修改外部 b
c = 300; // 修改外部 c
};
lambda();
cout << "b: " << b << ", c: " << c << endl; // 输出:b: 200, c: 300
return 0;
}
5. 初始化捕获(C++14 新增)
可以在捕获列表中初始化新变量,不需要依赖外部变量:
#include <iostream>
#include <memory>
using namespace std;
int main() {
// 初始化捕获:在 Lambda 内部创建一个 unique_ptr
auto lambda = [ptr = make_unique<int>(100)] {
cout << "初始化捕获的 ptr: " << *ptr << endl;
};
lambda();
return 0;
}
三、进阶:Lambda 的 3 个实用特性
1. mutable:修改值捕获的变量
值捕获的变量默认是 const 的,加 mutable 后可以修改(但修改的仍是副本,不影响外部)。
#include <iostream>
using namespace std;
int main() {
int a = 10;
// 加 mutable:可以修改值捕获的副本
auto lambda = [a]() mutable {
a = 20; // ✅ 可以修改(但改的是副本)
cout << "内部 a: " << a << endl;
};
lambda();
cout << "外部 a: " << a << endl; // 输出:外部 a: 10(不受影响)
return 0;
}
2. 泛型 Lambda(C++14 新增)
参数类型用 auto,让 Lambda 像模板函数一样通用:
#include <iostream>
using namespace std;
int main() {
// 泛型 Lambda:参数类型自动推导
auto add = [](auto x, auto y) {
return x + y;
};
cout << add(1, 2) << endl; // 输出:3(int)
cout << add(1.5, 2.5) << endl; // 输出:4.0(double)
cout << add(string("Hello"), string(" World")) << endl; // 输出:Hello World(string)
return 0;
}
3. Lambda 作为回调函数(最常用场景)
Lambda 最常用的场景是作为 STL 算法的回调,比如 sort、for_each:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main() {
vector<int> nums = {3, 1, 4, 1, 5, 9};
// 用 Lambda 作为 sort 的比较函数(降序排序)
sort(nums.begin(), nums.end(), [](int a, int b) {
return a > b;
});
// 用 Lambda 遍历输出
for_each(nums.begin(), nums.end(), [](int num) {
cout << num << " ";
});
// 输出:9 5 4 3 1 1
return 0;
}
总结
Lambda 的构建核心是:
- 捕获列表:决定如何访问外部变量(值 / 引用 / 隐式 / 初始化);
- 参数列表:和普通函数一致,C++14 可用
auto做泛型; - 返回类型:编译器自动推导,复杂情况可显式指定;
- 实用场景:STL 算法回调、异步任务、快速构建匿名函数。
更多推荐

所有评论(0)