以下是一个捕获列表和参数列表均不为空的 Lambda 表达式示例,结合 std::function 展示其用法,并详细解析语法:
#include <functional>
#include <iostream>
#include <string>
int main() {
// 外部变量:将被Lambda表达式捕获
std::string prefix = "Result: ";
int multiplier = 2;
// 定义带捕获列表和参数列表的Lambda表达式,并赋值给std::function
std::function<void(int, double)> calculate = [prefix, &multiplier](int a, double b) {
// 捕获的变量:prefix(值捕获)、multiplier(引用捕获)
// 参数:a(int类型)、b(double类型)
double result = (a * multiplier) + b;
std::cout << prefix << result << std::endl;
};
// 调用Lambda表达式(通过std::function包装器)
calculate(3, 4.5); // 输出:Result: 10.5(计算过程:3*2 + 4.5 = 10.5)
// 修改引用捕获的变量(会影响Lambda内部的计算)
multiplier = 3;
calculate(3, 4.5); // 输出:Result: 13.5(计算过程:3*3 + 4.5 = 13.5)
return 0;
}
语法解析
1. 捕获列表 [prefix, &multiplier]
捕获列表用于指定 Lambda 表达式如何访问外部作用域的变量,这里包含两个变量:
prefix:前面没有&,表示值捕获(拷贝外部变量的副本到 Lambda 内部)。 特点:Lambda 内部修改prefix不会影响外部的prefix,外部修改也不会影响 Lambda 内部的副本。&multiplier:前面有&,表示引用捕获(直接引用外部变量)。 特点:Lambda 内部对multiplier的修改会同步到外部,外部修改也会直接影响 Lambda 内部的使用(如示例中multiplier=3后,计算结果变化)。
捕获列表的其他常见形式:
[=]:值捕获所有外部变量(Lambda 内部使用副本)。[&]:引用捕获所有外部变量(Lambda 内部使用引用)。[this]:在类成员函数中,捕获当前对象的this指针(可访问类成员)。
2. 参数列表 (int a, double b)
参数列表与普通函数的参数列表语法一致,用于定义 Lambda 表达式接收的输入参数:
int a:第一个参数,整数类型。double b:第二个参数,双精度浮点类型。
调用 Lambda 时(如 calculate(3, 4.5)),需传入与参数列表类型、顺序匹配的实参(3 对应 a,4.5 对应 b)。
3. 函数体 { ... }
函数体包含 Lambda 表达式的执行逻辑,这里:
- 使用捕获的
prefix(值捕获,固定为"Result: ")和multiplier(引用捕获,可被外部修改)。 - 使用参数
a和b进行计算:(a * multiplier) + b。 - 输出结果:
std::cout << prefix << result << std::endl。
4. 类型匹配与调用
- 示例中 Lambda 表达式的签名为
void(int, double)(无返回值,接收int和double参数),与std::function<void(int, double)>的类型匹配,因此可以赋值。 - 调用时通过
calculate(3, 4.5)触发执行,与调用普通函数的语法完全一致。
核心特点总结
- 捕获列表:控制 Lambda 对外部变量的访问方式(值 / 引用),实现 “带状态的函数”。
- 参数列表:定义输入接口,使 Lambda 可以像普通函数一样接收参数。
- 结合
std::function后,可将 Lambda 作为变量存储、传递,广泛用于回调函数、事件处理等场景。