lambda 表达式是 C++11用于在一定场景下代替仿函数的新特性。lambda 表达式的书写格式为:
[capture-list](parameters)mutable->return-type{statement}
[capture-list]
:捕捉列表。编译器通过[]来判断接下来的代码是不是 lambda 函数,所以 [] 不可省略,捕捉列表能够捕捉上下文的变量提供 lambda 函数使用。
(parameters)
:参数列表。与普通函数的参数列表一致,如果函数没有参数,则可以连同 () 一起省略。
mutable
:默认情况下,lambda 函数总是一个 const 函数,mutable 可以取消其常量性。使用该修饰符时,参数列表不可省略。
->return-type
:返回值类型。用追踪返回类型形式声明函数的返回值类型,没有返回值时可以省略。返回值类型明确的情况下,也可省略,由编译器对返回类型进行推导。
{statement}
:函数体。在函数体内,除了参数以外,还可以使用所有捕获到的变量。
#include
#include
#include
using namespace std;
int main()
{
vector<int>v({ 5,2,7,6,9,1,4,8,3 });
auto less = [](const int& v1, const int& v2)->bool{return v1 > v2; };
sort(v.begin(), v.end(), less);
for (auto e : v)
{
cout << e << " ";
}
return 0;
}
lambda 也可以直接作为函数的参数。
lambda的 [capture-list]
描述了上下文中哪些数据可以被 lambda 使用,以及使用的方式是传值还是引用。
[var]
:表示传值捕捉变量 var。
[=]
:表示传值捕捉父作用域中的所有变量(包括this)。
[&var]
:表示引用传递捕捉变量 var。
[&]
:表示引用传递捕捉父作用域中的所有变量(包括this)。
[this]
:表示传值捕捉当前的 this 指针。注意:
- 父作用域指包含 lambda 函数的语句块。
- 捕捉列表不允许变量重复传递,否则就会导致编译器错误。
演示:
[] 内也可以部分传值部分引用:
但默认情况下,lambda 函数总是一个 const 函数,如果在函数体内部对变量进行更改,需要在参数列表后添加 mutable
关键字。
#include
using namespace std;
int main()
{
int a = 1, b = 2, c = 3;
auto func = [a, b, c]()mutable
{
a++;
b++;
c++;
cout << a <<" " << b << " " << c << endl;
};
func();
cout << a << " " << b << " " << c << endl;
return 0;
}
同时,这种捕捉是传值调用,如果需要让函数体内的更改对外部产生影响,就需要添加 &
引用。(注意这里 &
不是表示取地址)
#include
using namespace std;
int main()
{
int a = 1, b = 2, c = 3;
auto func = [&a, &b, &c]()mutable
{
a++;
b++;
c++;
cout << a <<" " << b << " " << c << endl;
};
func();
cout << a << " " << b << " " << c << endl;
return 0;
}
lambda表达式本质就是仿函数,编译器通过生成 uuid 防止仿函数的类名出现重复。