目录
定义
Lambda 表达式是一种匿名函数,可以在需要函数对象的地方使用,简化了函数对象的定义和使用过程。Lambda 表达式可以用于替代显式地创建函数对象或传递函数指针的情况。尤其适用于一些只在特定上下文中使用的函数功能。lambda表达式与普通函数类似,也有参数列表、返回值类型和函数体,只是它的定义方式更简洁,并且可以在函数内部定义。
语法
Lambda 表达式的一般语法形式为:
[capture-list](parameters) -> return-type {// 函数体}
capture-list
指定了捕获的变量列表(可选)。
parameters
指定了函数参数列表。
return-type
指定了返回类型(可选)。
{}
中是函数体,表示 Lambda 表达式的执行逻辑。
捕获列表
尽管Lambda表达式常常会被用在一个函数里,但它只能访问外部的全局变量而并不能访问函数里的局部变量,而这个捕获列表就是这Lambda表达式提供一个函数内的局部变量列表,只要被列在了列表内,那么表达式都可以对其进行访问。Lambda会将这些变量信息和自身放在一起,通常我们把它们这个整体叫作闭包(enclosure)。
[] 什么也不捕获,不可访问函数内的局部变量,只可访问全局变量
[=] 按值的方式捕获函数局部作用域里的所有变量
[&] 按引用的方式捕获函数局部作用域里的所有变量
[=, &a] 除了变量a之外,按值的方式捕获所有局部变量,变量a使用引用的方式来捕获。这里可以按引用捕获多个,例如 [=, &a, &b,&c]。这里注意,如果前面加了=,后面加的具体的参数必须以引用的方式来捕获,否则会报错。
[&, a] 除了变量a之外,按引用的方式捕获所有局部变量,变量a使用值的方式来捕获。这里后面的参数也可以多个,例如 [&, a, b, c]。这里注意,如果前面加了&,后面加的具体的参数必须以值的方式来捕获,否则会报错。
[a, &b] 以值的方式捕获a,引用的方式捕获b,也可以捕获多个。
[this] 在成员函数中,也可以直接捕获this指针,(其实在成员函数中,[=]和[&]也会捕获this指针)。
注意:
值捕获时,编译器会把捕获到的值作为类的成员变量,并且变量是以值的方式传递的。需要注意的时,如果所有的参数都是值捕获的方式,那么生成的operator()函数是const函数的,是无法修改捕获的值的,哪怕这个修改不会改变lambda表达式外部的变量,如果想要在函数内修改捕获的值,需要加上关键字 mutable。
示例
#include <iostream>
int main() {
int a = 5;
int b = 3;
auto sum = [](int x, int y) -> int {
return x + y;
};
int result = sum(a, b);
std::cout << "结果: " << result << std::endl;
return 0;
}
在上面的示例中,我们定义了一个 Lambda 表达式,它接受两个整数参数并返回它们的和。
使用
auto
关键字将 Lambda 表达式赋值给sum
变量,这样就创建了一个函数对象。然后,我们调用
sum
函数对象并传递两个整数参数a
和b
,将返回的结果赋值给result
变量。最后,我们打印出result
的值。Lambda 表达式还支持捕获外部变量,可以在
[capture list]
中指定要捕获的变量。捕获列表可以是空的([]),也可以使用引用方式或传值方式捕获变量。
关键字auto
auto
是 C++11 引入的关键字,用于进行类型推导。它可以让编译器根据变量初始化表达式的类型自动推断出变量的类型。使用auto
可以简化代码并增加可读性。
auto num = 5; // 推导为 int 类型
auto name = "John"; // 推导为 const char* 类型
auto result = calculate_result(); // 推导为函数返回值的类型
std::vector<int> numbers = {1, 2, 3};
for (auto it = numbers.begin(); it != numbers.end(); ++it) {
// 使用 auto 推导迭代器类型
std::cout << *it << " ";
}
在上面的示例中,我们使用
auto
关键字声明了多个变量。编译器会根据初始化表达式自动推导这些变量的类型。第一个示例中,
num
被推导为int
类型,因为它被初始化为一个整数。第二个示例中,
name
被推导为const char*
类型,因为它被初始化为一个字符串字面量。第三个示例中,
result
被推导为某个函数的返回值类型,具体类型取决于calculate_result
函数的返回类型。最后一个示例中,我们在循环中使用
auto
推导迭代器的类型,无需显式指定迭代器类型。总之,
auto
关键字可以方便地使代码更简洁、可读性更高,并且减少了类型的重复和维护的工作量。但需要注意,使用auto
时要确保初始化表达式能够明确推导出变量的类型,避免产生二义性。