目录
- 定义
- 基本语法
- 函数对象(仿函数)
- 例子
- sort中的Lambda的运用
- 变量的捕获
- 优点
定义
Lambda表达式是C++11引入的一个新特性,用于定义匿名函数对象。它允许在代码中临时定义函数或函数对象,而不需要像传统方式那样定义一个单独的函数。Lambda表达式特别适用于STL算法(如std::sort, std::for_each等)中作为回调函数,能够显著提高代码的简洁性和可读性。
基本语法
- 第一种 :
[捕获变量](参数列表) 可选限定符->返回类型{ //函数代码 }
- 第二种:
[](int a, int b){ //函数代码 }
1.第二种将自动推导返回值
2.可选限定符可不写
函数对象(仿函数)
- 是一个通过重载 operator() 使得一个对象能够像函数一样被调用的类或结构体。
- 在 C++ 中,函数对象是一种比普通函数指针更为灵活的方式,它不仅可以执行函数的任务,还能存储和操作额外的状态信息。
- 通过重载 operator(),对象就变得可以像普通函数一样被调用。
例子
-
Lambda表达式: auto p = [x, y](int a, int b) -> float { return x * y + a * b; }; 这行代码定义了一个Lambda表达式,并将它赋值给变量p。该Lambda接受两个整数参数(a 和 b),并返回一个浮点数。
-
[x, y]
:捕获外部变量x和y,按值捕获。 -
(int a, int b)
:Lambda的参数列表,表示它接受两个整数参数。 -
-> float
:返回类型是float。 -
return x * y + a * b;
:Lambda的函数体,计算表达式并返回结果。 -
类型推导: 由于使用了 auto,变量 p 会被推导为Lambda类型。实际上,p 的类型是一个匿名的函数对象(一个可调用对象)。
p 是什么类型?
p 是一个 函数对象类型(函数对象也被叫做仿函数),而不是一个函数指针。
Lambda表达式在C++中生成一个类,Lambda捕获的变量和函数体成为这个类的成员。Lambda表达式返回的就是这个类的实例。
这个类的 operator() 被重载,以实现调用行为。
int main()
{int x = 7;float y = 3.0;auto p = [x, y](int a, int b) -> float {return x * y + a * b;};cout << p(10, 20);return 0;
}
sort中的Lambda的运用
vector<float> numbers{ 1.1, 2,2,3.5,-1.4,29.2,6.0,33,12.1,5};sort(numbers.begin(), numbers.end(), [](float a, float b) {return a < b; });for (auto x : numbers){cout << x << ' ';}
变量的捕获
有两种:按值捕获 / 按引用捕获
-
按值捕获
不影响原来捕获变量的值,类似于函数传值。
如下不影响外面的x变量,此x为局部变量,与外面的x无关。
[x, y](int a, int b) -> float { x+=1.5; return x * y + a * b; };
-
按引用捕获
会影响捕获变量的值,类似于函数传引用。
如下影响外面的x变量,此x为外部变量,就是外面的x。
[&x, &y](int a, int b) -> float { x+=1.5; return x * y + a * b; };
-
默认按值捕获
按值捕获外部所有变量。
[=](int a, int b) -> float { x+=1.5; return x * y + a * b; };
-
默认按引用捕获
按引用捕获外部所有变量。
[&](int a, int b) -> float { x+=1.5; return x * y + a * b; };
-
作用域
- 如下,按引用捕获了x,y。
- 但在main函数中x,y已失效,生命周期结束,引用无效,代码错误。
- 按值捕获没有此问题
-
在一个类中定义Lambda时,还可以捕获
this
指针或者*this
。这样Lambda函数就可以像类中成员函数一样访问类的成员。- 捕获
this
为按引用捕获 - 捕获
*this
为按值捕获 - 如果使用默认捕获,无论是按值还是按引用,this都是按引用捕获的
- 捕获
-
在函数中,除了可以使用捕获的变量,也可以使用静态变量,全局变量。
优点
可以将左边代码缩短为一两三行。