C++11 引入了 lambda 表达式,为开发者提供了一种简洁的方式来定义匿名函数。下面详细介绍 lambda 的语法、捕获方式及实际应用示例。
语法结构
lambda 表达式的基本结构如下:
[capture](parameters) -> return_type { statements; }
- 捕获列表 ([capture]):指定要捕获的变量,可以是值捕获(=)或引用捕获(&),也可以单独捕获特定变量。
- 参数列表 (parameters):与普通函数类似,可以接受多个参数,类型和名称。
- 返回类型 (-return_type):可选,通常由编译器自动推导。
- 函数体 {statements;}:lambda 的执行代码。
捕获方式
捕获方式决定了 lambda 如何访问外部变量:
- 默认捕获:
- [=]:按值捕获所有外部变量。
- [&]:按引用捕获所有外部变量。
- 显式捕获:
- [x, &y]:捕获 x 的值,y 的引用。
- [this]:捕获当前对象的指针(用于成员函数)。
- 混合捕获:
- [=, &a]:值捕获默认,加上引用捕获 a。
示例
1. 最简单的 lambda
[]() { std::cout << "Hello, lambda!" << std::endl; };
此 lambda 不接受参数,执行一个输出语句。
2. 带参数的 lambda
auto add = [](int a, int b) { return a + b; };
std::cout << add(5, 3) << std::endl; // 输出 8
3. 捕获外部变量
int x = 5;
auto lambda = [x]() {
std::cout << x << std::endl;
};
lambda(); // 输出 5
4. 修改外部变量
int y = 10;
auto lambda = [&y]() { y = 20; };
lambda();
std::cout << y << std::endl; // 输出 20
作为函数参数
lambda 可以传递给接受函数指针或 std::function 的函数。
示例:STL 算法中的使用
#include
#include
#include
int main() {
std::vector vec = {3,1,4,1,5};
std::sort(vec.begin(), vec.end(), [](int a, int b) {
return a > b;
});
for (int num : vec) {
std::cout << num << " ";
}
return 0;
}
此处,lambda 用于自定义排序顺序。
Lambda 作为返回值
可以将 lambda 作为函数的返回值,使用 std::function 来接收。
#include
std::function createAdder() {
return [](int a, int b) { return a + b; };
}
int main() {
auto add = createAdder();
std::cout << add(3, 4) << std::endl; // 输出7
return 0;
}
注意事项
- 变量生命周期:捕获的变量必须在 lambda 执行时有效。避免在 lambda 之后使用已经销毁的变量。
- 逃逸和生命周期:在多线程环境中,如果 lambda 被传递给其他线程,确保捕获的变量在目标线程仍然有效。
- this 捕获:在成员函数内的 lambda 捕获 this 时,必须确保 lambda 执行时对象仍有效。
总结
lambda 表达式简化了匿名函数的定义,提高了代码的灵活性和可读性。在回调、事件处理、并行编程等场景中非常有用。通过合理的变量捕获和返回值处理,可以充分利用 lambda 的强大功能。