C++ labmbd表达式
文章目录
- C++ Lambda 表达式详解
- 1. Lambda 表达式的组成部分:
- 2. Lambda 语法示例
- (1) 最简单的 Lambda
- (2) 带参数的 Lambda
- (3) 指定返回类型的 Lambda
- 3. 捕获外部变量
- (1) 值捕获(复制)
- (2) 引用捕获
- (3) 捕获所有变量
- 4. Lambda 在 STL 中的应用
- 5. Lambda 作为 `std::function`
- 6. 可变 (`mutable`) Lambda
- 7. Lambda 递归
- 总结
C++ Lambda 表达式详解
Lambda 表达式(也称为匿名函数)是一种简洁的方式来定义即用即弃的函数对象,特别适用于回调、并行算法和函数式编程风格。Lambda 表达式的基本语法如下:
[capture](parameters) -> return_type { function_body }
1. Lambda 表达式的组成部分:
组件 | 作用 |
---|---|
[capture] | 捕获外部作用域变量 |
(parameters) | 形参列表(可省略) |
-> return_type | 返回值类型(可省略,编译器可推导) |
{ function_body } | 函数体 |
2. Lambda 语法示例
(1) 最简单的 Lambda
#include <iostream>
int main() {
auto lambda = [] { std::cout << "Hello, Lambda!" << std::endl; };
lambda(); // 调用 lambda
return 0;
}
说明:
[]
表示没有捕获外部变量。- 没有参数和返回值,直接执行
{}
内部的代码。
(2) 带参数的 Lambda
#include <iostream>
int main() {
auto add = [](int a, int b) { return a + b; };
std::cout << add(3, 5) << std::endl; // 输出 8
return 0;
}
说明:
[](int a, int b) { return a + b; }
是一个接收两个int
参数并返回它们和的 Lambda 表达式。auto add
变量接收 Lambda,可像普通函数一样调用。
(3) 指定返回类型的 Lambda
#include <iostream>
int main() {
auto divide = [](int a, int b) -> double { return (double)a / b; };
std::cout << divide(5, 2) << std::endl; // 输出 2.5
return 0;
}
说明:
-> double
明确指定了返回类型,否则a / b
可能会被推导为int
。
3. 捕获外部变量
Lambda 可以访问其作用域内的变量,但必须通过捕获列表 []
指定是否捕获它们。
(1) 值捕获(复制)
#include <iostream>
int main() {
int x = 10;
auto lambda = [x]() { std::cout << x << std::endl; };
x = 20; // lambda 捕获的是 10,不受影响
lambda(); // 输出 10
return 0;
}
说明:
[x]
捕获x
的值,lambda
内部访问的是捕获时的值,不受x
变化影响。
(2) 引用捕获
#include <iostream>
int main() {
int x = 10;
auto lambda = [&x]() { std::cout << x << std::endl; };
x = 20; // lambda 捕获的是引用,会受影响
lambda(); // 输出 20
return 0;
}
说明:
[&x]
捕获x
的引用,因此x
的修改会影响 Lambda 内部的x
。
(3) 捕获所有变量
#include <iostream>
int main() {
int a = 5, b = 10;
auto value_capture = [=]() { std::cout << a << " " << b << std::endl; };
auto ref_capture = [&]() { std::cout << a << " " << b << std::endl; };
a = 20; b = 30;
value_capture(); // 仍然输出 5 10(值捕获不会变)
ref_capture(); // 输出 20 30(引用捕获受外部变量影响)
return 0;
}
说明:
[=]
:值捕获所有变量(a, b
被拷贝)。[&]
:引用捕获所有变量(a, b
直接访问原始变量)。
4. Lambda 在 STL 中的应用
Lambda 在 std::sort
等标准库函数中很常见:
#include <iostream>
#include <vector>
#include <algorithm>
int main() {
std::vector<int> nums = {4, 2, 7, 1, 9};
std::sort(nums.begin(), nums.end(), [](int a, int b) { return a < b; });
for (int num : nums) {
std::cout << num << " "; // 输出 1 2 4 7 9
}
return 0;
}
说明:
std::sort
需要一个比较函数,Lambda 可直接提供简洁的方式。
5. Lambda 作为 std::function
Lambda 还能存储到 std::function
变量中,方便传递:
#include <iostream>
#include <functional>
int main() {
std::function<int(int, int)> multiply = [](int a, int b) { return a * b; };
std::cout << multiply(3, 4) << std::endl; // 输出 12
return 0;
}
6. 可变 (mutable
) Lambda
默认情况下,值捕获的 Lambda 内部不能修改捕获的变量:
#include <iostream>
int main() {
int x = 10;
auto lambda = [x]() mutable { x = 20; std::cout << x << std::endl; };
lambda(); // 输出 20
std::cout << x << std::endl; // 仍然是 10(外部 x 没变)
return 0;
}
说明:
mutable
允许修改值捕获的x
,但该修改不会影响原始x
。
7. Lambda 递归
Lambda 默认不能递归调用自己,但可以用 std::function
解决:
#include <iostream>
#include <functional>
int main() {
std::function<int(int)> factorial = [&](int n) {
return (n <= 1) ? 1 : n * factorial(n - 1);
};
std::cout << factorial(5) << std::endl; // 输出 120
return 0;
}
说明:
std::function<int(int)>
用于存储 Lambda,使其能递归调用自身。
总结
语法 | 说明 |
---|---|
[] {} | 无参数、无返回值的 Lambda |
[](int x) { return x * 2; } | 带参数和返回值的 Lambda |
[x] {} | 值捕获变量 x |
[&x] {} | 引用捕获变量 x |
[=] {} | 值捕获所有变量 |
[&] {} | 引用捕获所有变量 |
mutable | 允许修改值捕获的变量 |
std::function | 存储 Lambda 并支持递归 |
Lambda 表达式是 C++ 现代编程的重要特性,广泛用于 STL、并行计算和回调函数中。