1. 什么是 Lambda 表达式?
Lambda 表达式是 C++11 引入的一种特性,允许定义匿名函数(没有名字的函数),并且可以像普通函数一样调用,甚至可以作为参数传递给其他函数。
基本语法:
[capture_list](parameters) -> return_type { function_body };
[capture_list]
:捕获列表,决定外部变量如何被 lambda 捕获。(parameters)
:参数列表,与普通函数的参数类似。-> return_type
(可选):返回类型,通常可以省略,由编译器自动推断。{ function_body }
:函数体,包含要执行的具体逻辑。
2. Lambda 表达式的基本用法
-
无参数、无返回值:
[]() { std::cout << "Hello, Lambda!" << std::endl; }();
输出:
Hello, Lambda!
-
有参数、返回值:
auto add = [](int a, int b) { return a + b; }; std::cout << add(2, 3) << std::endl; // 输出 5
-
显式指定返回类型:
auto divide = [](int a, int b) -> double {return static_cast<double>(a) / b; }; std::cout << divide(5, 2) << std::endl; // 输出 2.5
3. 捕获列表([capture_list]
)
捕获列表决定 lambda 如何访问外部作用域中的变量。可以按值捕获或按引用捕获。
(1) 空捕获列表:[]
- 不捕获任何外部变量。
- 仅适用于 lambda 完全独立的情况。
示例:
auto print = []() { std::cout << "Independent Lambda" << std::endl; };
print();
(2) 按值捕获:[x]
- 捕获外部变量
x
的副本,lambda 内的修改不会影响原变量。
示例:
int x = 5;
auto lambda = [x]() { std::cout << x << std::endl; };
lambda(); // 输出 5
x = 10; // 修改原变量
lambda(); // 仍输出 5
(3) 按引用捕获:[&x]
- 捕获外部变量
x
的引用,lambda 内的修改会影响原变量。
示例:
int x = 5;
auto lambda = [&x]() { x += 10; };
lambda();
std::cout << x << std::endl; // 输出 15
(4) 捕获所有外部变量:[=]
和 [&]
[=]
:按值捕获所有外部变量。[&]
:按引用捕获所有外部变量。
示例:
int x = 5, y = 10;
auto lambda1 = [=]() { std::cout << x + y << std::endl; }; // 按值捕获
auto lambda2 = [&]() { x += y; }; // 按引用捕获
lambda1(); // 输出 15
lambda2();
std::cout << x << std::endl; // 输出 15
(5) 混合捕获:[=, &x]
和 [&, x]
[=, &x]
:按值捕获所有变量,但对x
按引用捕获。[&, x]
:按引用捕获所有变量,但对x
按值捕获。
示例:
int x = 5, y = 10;
auto lambda = [=, &y]() { y += x; }; // x 按值,y 按引用
lambda();
std::cout << y << std::endl; // 输出 15
4. 使用 Lambda 表达式排序
Lambda 表达式经常用于自定义排序规则,例如在 std::sort
中。
-
升序排序:
std::vector<int> vec = {5, 2, 9, 1}; std::sort(vec.begin(), vec.end(), [](int a, int b) { return a < b; }); // vec: {1, 2, 5, 9}
-
降序排序:
std::sort(vec.begin(), vec.end(), [](int a, int b) { return a > b; }); // vec: {9, 5, 2, 1}
-
复杂排序规则:
std::sort(vec.begin(), vec.end(), [](int a, int b) {if (a % 2 == b % 2) return a > b; // 同为奇数或偶数,按降序return a % 2 < b % 2; // 偶数优先 }); // 假设 vec = {5, 2, 4, 7, 8} // 排序后:{8, 4, 2, 7, 5}
5. Lambda 表达式的实际应用场景
- 代替普通函数:用于实现一次性的功能,减少定义单独函数的冗余。
- 自定义排序:灵活定义排序规则(如
std::sort
)。 - 回调函数:用于事件响应或异步处理(如
std::for_each
)。 - 函数式编程:与标准库的函数式接口(如
std::transform
)结合使用。 - 捕获变量用于计算:简化闭包的实现。
6. 示例:捕获外部变量的高级应用
int base = 10;
auto multiplier = [base](int x) { return base * x; };std::cout << multiplier(2) << std::endl; // 输出 20
- 捕获
base
,并使用其值进行计算。 - 这使得 lambda 可以与外部变量结合实现更多功能。
7. 总结
Lambda 表达式的优势:
- 简洁:减少了定义额外函数的冗余代码。
- 灵活:可以捕获外部变量,轻松实现闭包。
- 高效:与标准库算法结合(如
std::sort
、std::transform
),使代码更清晰。
常用模式:
- 无捕获:
[]() {}
。 - 按值捕获:
[x]() {}
或[=]() {}
。 - 按引用捕获:
[&x]() {}
或[&]() {}
。 - 混合捕获:
[=, &x]
或[&, x]
。
Lambda 表达式是现代 C++ 编程的重要工具,值得熟练掌握!