lambda表达式:
这是C++11引入的一种新特性,它可以让您在需要定义函数对象的地方,直接编写一个匿名的、可以捕获上下文变量的函数体,非常适合用作回调函数、临时计算或定义小型函数对象。
lambda表达式与普通函数类似,也有参数列表、返回值类型和函数体,只是它的定义方式更简洁,并且可以在函数内部定义。
lambda表达式的语法:
lambda表达式的一般形式如下:
[capture] (parameters) mutable -> return-type { body }
其中:
[capture]
:捕获列表,表示lambda表达式可以捕获哪些上下文中的变量,以值或引用的方式。捕获列表可以为空,表示不捕获任何变量,也可以使用=
或&
表示按值或引用捕获所有变量,还可以指定具体的变量名,用逗号分隔。例如:
[a, &b] // 按值捕获a,按引用捕获b
[=, &c] // 按值捕获所有变量,但按引用捕获c
[&] // 按引用捕获所有变量
[this] // 捕获当前的this指针
(parameters)
:参数列表,表示lambda表达式可以接受哪些参数,与普通函数的参数列表相同。参数列表可以为空,表示不接受任何参数,也可以使用auto
来推断参数类型。例如:
() // 不接受任何参数
(int x, double y) // 接受两个参数,类型分别为int和double
(auto x, auto y) // 接受两个参数,类型由编译器推断
-
mutable
:修饰符,表示lambda表达式的函数体可以修改按值捕获的变量,否则默认是常量。如果使用了mutable
,则参数列表不能省略。例如:[x] () mutable { x++; } // 可以修改按值捕获的x [x] () { x++; } // 错误,不能修改常量x
-
-> return-type
:返回值类型,表示lambda表达式的返回值的类型,与普通函数的返回值类型相同。返回值类型可以省略,由编译器根据函数体的返回语句推断。例如:() -> int { return 42; } // 返回值类型为int () { return 42; } // 返回值类型由编译器推断为int
-
{ body }
:函数体,表示lambda表达式的具体逻辑,与普通函数的函数体相同。函数体可以使用捕获列表和参数列表中的变量,也可以调用其他函数或lambda表达式。例如:[a] (int x) { return a + x; } // 函数体返回a和x的和 [] { std::cout << "Hello" << std::endl; } // 函数体打印一句话
lambda表达式的使用:
lambda表达式的使用方法是在定义的地方加上一对圆括号,表示调用该lambda表达式,括号中可以传递参数,也可以为空。lambda表达式的返回值可以赋值给一个变量,也可以作为另一个函数的参数或返回值。lambda表达式的使用场景有很多,
举例:
当不使用 lambda表达式时代码:
#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
// Define a function to print an integer
void print_int(int x) {
std::cout << x <<",";
}
// Define a function object to compare two integers by their absolute values
struct abs_compare {
bool operator()(int x, int y) {
return std::abs(x) > std::abs(y);
}
};
int main() {
std::vector<int> v1 = {1, -12, 3, -4, 5,6,7,-9};
// Use the print_int function as the third argument of std::for_each
std::for_each(v1.begin(), v1.end(), print_int);
std::cout << std::endl;
// Use the abs_compare function object as the third argument of std::sort
std::sort(v1.begin(), v1.end(), abs_compare());
// Use the print_int function again
std::for_each(v1.begin(), v1.end(), print_int);
return 0;
}
当使用 lambda表达式时的代码:
#include <iostream>
#include <vector>
#include <algorithm>
int main()
{
std::vector<int> v1 = {1, -12, 3, -4, 5,6,7,-9};
// Use brackets around the lambda expression
std::for_each(v1.begin(),v1.end(), [] (const int& x){std::cout<<x<<",";});
std::cout<<std::endl;
// Use braces around the lambda body
std::sort(v1.begin(),v1.end(), [] (const int& x,const int& y){return abs(x) > abs(y);});
std::for_each(v1.begin(),v1.end(),[](const int &x){std::cout<<x<<",";});
return 0;
}
例如:
-
作为回调函数,例如在STL的算法中,可以使用lambda表达式来自定义比较函数、谓词函数、操作函数等。例如:
std::vector<int> v{1, 2, 3, 4, 5}; // 使用lambda表达式作为比较函数,按照绝对值降序排序 std::sort(v.begin(), v.end(), [] (const int &x,const int &y) { return abs(x) > abs(y); }); // 使用lambda表达式作为谓词函数,查找第一个偶数 auto it = std::find_if(v.begin(), v.end(), [] (const int &x) { return x % 2 == 0; }); // 使用lambda表达式作为操作函数,对每个元素加一 std::for_each(v.begin(), v.end(), [] (const int &x) { x++; });
-
作为临时计算,例如在需要一个简单的计算结果时,可以使用lambda表达式来封装计算逻辑,而不需要定义一个单独的函数。
例如:使用lambda表达式计算两个数的最大公约数
// 定义一个lambda表达式,接受两个参数a和b,返回它们的最大公约数
auto gcd = [] (int a, int b) -> int {
if (b == 0) return a;
else return gcd(b, a % b);
};
// 调用lambda表达式,传入24和36
int result = gcd(24, 36);
// 输出结果
std::cout << "最大公约数是:" << result << std::endl;
-
作为小型函数对象,例如在需要一个简单的函数对象时,可以使用lambda表达式来定义一个匿名的函数对象,而不需要定义一个单独的类或结构体。
例如:使用lambda表达式定义一个函数对象,用于计算两个数的和
auto adder = [](const int &x,const int &y) { return x + y; };
std::cout << adder(1, 2) << std::endl; // 输出3
参考链接:
C++ Lambda表达式的完整介绍 - 知乎 (zhihu.com)