目录
一.简介
1.基本概念
2.语法
二.使用示例
示例1:基础用法
示例2:带参数和返回值
示例3:捕获外部变量
示例4:修改值捕获的值(mutable 关键字)
示例5:在 STL 算法中使用(常用)
三.注意事项
四.补充
Lambda表达式是C++11引入的一种匿名函数的实现形式,能让你在代码中方便、快速地定义小型临时函数,尤其在需要简洁表达式、回调函数或函数对象时。
Lambda表达式实质上是匿名函数对象(closure),可以访问其定义时的外部作用域变量。
它弥补了传统函数指针和函数对象(functor
)的不足,具有以下特点:
匿名性:无需显式命名,可直接在需要的地方定义。
闭包特性:可以捕获作用域内的变量,形成闭包。
灵活性:支持多种捕获模式、参数传递和返回值类型。
与 STL 完美结合:常用于算法(如
sort
,for_each
)的回调函数。
[捕获列表] (参数列表) -> 返回类型 {
// 函数体
}
(1)捕获列表(Capture List)
定义 lambda 如何访问外部变量:
[]
:不捕获任何外部变量。
[=]
:以 值捕获 所有外部变量。
[&]
:以 引用捕获 所有外部变量。
[var]
:值捕获特定变量var
。
[&var]
:引用捕获特定变量var
。混合捕获:
[=, &x]
(值捕获所有变量,但x
是引用捕获)。
(2)参数列表(Parameters)
与普通函数参数类似,支持默认参数(C++14 起)。
(3)返回类型(Return Type)
可省略,编译器自动推导。
需显式声明时使用 ->类型。
(4)函数体(Body)
包含实际执行的代码。
auto print = []() {
std::cout << "Hello Lambda!";
};
print(); // 输出: Hello Lambda!
auto add = [](int a, int b) -> int { //->int指定返回类型
return a + b;
};
std::cout << add(3, 4); // 输出: 7
int x = 10, y = 20;
auto sum = [x, &y]() {
return x + y; // x 是值捕获,y 是引用捕获
};
y = 30;
std::cout << sum(); // 输出: 10 + 30 = 40
捕获列表的作用是让 Lambda 表达式能够访问其定义所在作用域中的外部变量。
[x, &y]()
中,x
是通过值捕获的方式被捕获的。值捕获意味着 Lambda 表达式会在定义时复制一份 x
的值,存储在 Lambda 对象内部。此后,Lambda 表达式内部使用的 x
是这个副本,而不是原始的 x
。即使在 Lambda 表达式定义之后,外部的 x
值发生了改变,Lambda 表达式内部的 x
值也不会受到影响。
y
是通过引用捕获的方式被捕获的。引用捕获意味着 Lambda 表达式内部使用的 y
是外部 y
的引用,而不是副本。因此,Lambda 表达式内部对 y
的访问和修改实际上是对外部 y
变量的访问和修改。同样,外部代码对 y
的修改也会直接影响到 Lambda 表达式内部的 y
。
mutable
关键字)#include
int main() {
int count = 0;
auto increment = [count]() mutable {
count++; // 允许修改值捕获的变量
return count;
};
int result = increment();
std::cout << "Result of increment(): " << result << std::endl;
std::cout << "External count: " << count << std::endl;
return 0;
}
(1)sort
#include
#include
#include
int main() {
std::vector nums = {3, 1, 4, 1, 5};
std::sort(nums.begin(), nums.end(), [](int a, int b) {
return a > b; // 降序排序
});
// 输出排序后的结果
for (int num : nums) {
std::cout << num << " ";
}
std::cout << std::endl;
return 0;
}
(2 )find_if
#include
#include
#include
int main() {
std::vector numbers = {1, 2, 3, 4, 5};
// 使用 Lambda 表达式查找第一个大于 3 的元素
auto it = std::find_if(numbers.begin(), numbers.end(), [](int num) { return num > 3; });
if (it != numbers.end()) {
std::cout << "First number greater than 3: " << *it << std::endl;
}
return 0;
}
- 生命周期问题:当使用引用捕获时,需要确保被捕获的变量在 Lambda 表达式执行时仍然有效。如果 Lambda 表达式在被捕获的变量销毁后执行,会导致未定义行为。
mutable
关键字:如果使用了mutable
,可以修改通过值捕获的变量,但这种修改只影响 Lambda 表达式内部的副本,不会影响外部的原始变量。- 性能问题:虽然 Lambda 表达式通常会被编译器内联,性能开销较小,但在某些复杂情况下,频繁创建和销毁 Lambda 对象可能会带来一定的性能损失。
1. C++14:支持泛型 lambda(auto
参数)和捕获初始化:
auto lambda = [value = 42]() { return value; };
2.C++17:允许 constexpr lambda
:
constexpr auto square = [](int x) { return x * x; };
static_assert(square(3) == 9); // 编译期计算
3.C++20:支持模板 lambda 和 [=, this]
显式捕获。