定义
Lambda表达式是C++11引入的一种函数对象的匿名表示方法。它可以用于定义轻量级的、临时的、内联的函数对象,通常用于函数式编程的场景。
语法结构
Lambda表达式的 基本语法 如下:
lambda表达式书写格式:[capture-list] (parameters) mutable -> return-type {
// 函数体 - statement
}
ambda表达式各部分说明:
[capture-list]
: 捕捉列表,该列表总是出现在lambda函数的开始位置,编译器根据[]来判断接下来的代码是否为lambda函数,捕捉列表能够捕捉上下文中的变量供lambda函数使用。(parameters)
:参数列表。与普通函数的参数列表一致,如果不需要参数传递,则可以连同()一起省略。mutable
:默认情况下,lambda函数总是一个const函数,mutable可以取消其常量性。使用该修饰符时,参数列表不可省略(即使参数为空)。->returntype
:返回值类型。用追踪返回类型形式声明函数的返回值类型,没有返回值时此部分可省略。返回值类型明确情况下,也可省略,由编译器对返回类型进行推导。{}
中是Lambda表达式的函数体,包含了实际要执行的代码逻辑。
需要注意的是:
在lambda函数定义中,参数列表和返回值类型都是可选部分,而捕捉列表和函数体可以为空。因此C++11中最简单的lambda函数为:[]{}
; 该lambda函数不能做任何事情
关于 捕获列表
捕捉列表描述了上下文中那些数据可以被lambda使用,以及使用的方式传值还是传引用。
- [var]:表示值传递方式捕捉变量var
- [=]:表示值传递方式捕获所有父作用域中的变量(包括this)
- [&var]:表示引用传递捕捉变量var
- [&]:表示引用传递捕捉所有父作用域中的变量(包括this)
- [this]:表示值传递方式捕捉当前的this指针
性质
- 父作用域指包含lambda函数的语句块
- 语法上捕捉列表可由多个捕捉项组成,并以逗号分割。例如:
[=, &a, &b]
:以引用传递的方式捕捉变量a和b,值传递方式捕捉其他所有变量[&,a, this]
:值传递方式捕捉变量a和this,引用方式捕捉其他变量
- 捕捉列表不允许变量重复传递,否则就会导致编译错误。例如:
比如:[=, a]:=已经以值传递方式捕捉了所有变量,捕捉a重复
- 在块作用域以外的lambda函数捕捉列表必须为空。
- 在块作用域中的lambda函数仅能捕捉父作用域中局部变量,捕捉任何非此作用域或者非局部变量都会导致编译报错。
- lambda表达式之间不能相互赋值,即使看起来类型相同
原因:Lambda表达式是一种匿名函数,它生成的函数对象是一个闭包。每个Lambda表达式都有其自己的类型,并且不同的Lambda表达式具有不同的类型。因此,Lambda表达式之间不能直接相互赋值。
可以使用 函数指针 / std::function
进行函数赋值
// 函数指针实现 函数赋值
void f1() {
std::cout << "hello" << std::endl;
}
void f2() {
std::cout << "hello" << std::endl;
}
int main()
{
void (*pf)();
pf = f1; // 将函数指针pf指向f1
pf(); // 调用f1函数
pf = f2; // 将函数指针pf指向f2
pf(); // 调用f2函数
return 0;
}
常见用法
1. 作为函数对象传递:
Lambda表达式可以作为参数传递给需要函数对象作为参数的函数,例如:
// 函数接受一个函数对象作为参数
void process(std::function<void(int)> func) {
// ...
}
// 调用时使用Lambda表达式作为参数
process([](int x) {
// Lambda表达式的逻辑
// ...
});
2. 在算法中使用:
Lambda表达式可以与标准库中的算法一起使用,用于指定算法的操作行为,例如:
std::vector<int> nums = {1, 2, 3, 4, 5};
// 使用Lambda表达式作为排序准则
std::sort(nums.begin(), nums.end(), [](int a, int b) {
return a < b;
});
// 使用Lambda表达式作为条件判断
auto it = std::find_if(nums.begin(), nums.end(), [](int num) {
return num > 3;
});
3. 自定义比较器:
Lambda表达式可以用来定义自定义的比较器,例如在容器排序或二叉搜索树中使用,例如:
struct Person {
std::string name;
int age;
};
std::vector<Person> people = {{"Alice", 25}, {"Bob", 30}, {"Charlie", 20}};
// 使用Lambda表达式定义自定义比较器
std::sort(people.begin(), people.end(), [](const Person& p1, const Person& p2) {
return p1.age < p2.age;
});
4. 异步编程:
Lambda表达式可以用于异步编程,例如与std::async一起使用,创建异步任务,例如:
auto future = std::async([]() {
// 异步任务的逻辑
// ...
return result;
});
// 获取异步任务的结果
auto result = future.get();