lambda
- lambda的介绍
- lambda的使用
- lambda的细节->捕捉列表
lambda的介绍
lambda是匿名函数,再适合的场景去使用可以提高代码的可读性。
场景:
假设有一个Goods类需要进行按照价格、数量排序
class Goods
{
string name;
size_t _price;//价格
int num;//数量
};
要是对一个类进行排序可以使用库函数sort(),但是sort()的最后一个参数是决定按照哪个成员排序,以及是排升序还是排降序的,所以最后一个参数就需要写成仿函数,假设用价格排升序:
struct ComparePriceGreater
{
bool operator()(Goods& g1,Goods& g2)
{
return g1.price>g2.prices;
}
};
//然后再传仿函数
sort(容器.begin(),容器.end(),ComparePriceGreater())
这样排列组合就需要写四个仿函数那这样就会减低代码的可读性,如果使用lambda就可以减少代码量,加强代码的可读性。
sort(容器.begin(),容器.end(),[](const Goods& g1, const Goods& g2)
{return g1.price>g2.price };)
lambda的使用
lambdad的组成部分:capture-listmutable->return-type{statement}
[capture-list]:叫做补做列表,该列表总是出现在lambda函数的开始位置,编译器根据[]来判断接下来的代码是否为lambda函数,捕捉列表能够捕捉上下文中的变量供lambda函数使用。
(parameters):叫做参数列表,和函数的参数列表是一样的,没有参数的时候可以省略
mutable:默认情况下,lambda函数总是一个const函数,mutable可以取消其常量性。使用该修饰符时,参数列表不可省略(即使参数为空)。
->return-type:返回值类型。用追踪返回类型形式声明函数的返回值类型,没有返回值时此部分可以省略。返回值类型明确情况下,也可省略,由编译器对返回类型进行推导。
{statement}:函数主体,在该函数体内,除了可以使用其参数外,还可以使用所有捕获到的变量。
int main()
{
auto add = [](int a)mutable->int {return ++a; };
cout << add(1) << endl;
return 0;
}
需要注意:函数体写完之后要加上;
lambda的细节->捕捉列表
[]捕捉列表可以捕捉程序上下文中的变量给函数体使用,是值传递还是应用传递。
[var]:值传递捕捉var
[=]:值传递捕捉此作用域中的所有变量
[&var]:引用传递捕捉var
[&]:引用传递捕捉此作用域中的全部变量
[this]:值传递捕捉this指针
注意点:
- 捕捉传递可以是多个捕捉项,如:[=,&a,&b]
- 不能重复传递捕捉同一个变量,如:[=,a]
- lambda是一个匿名函数,要用auto来接收,或者function和bind包装器
- lambda若是全局的,捕捉列表一定要为空
- 两个相同的lambda不可以赋值
- lambda只可以捕捉本作用域的局部变量,捕捉全局和非此作用域的变量会报错
例子: 写一个交换两个数的lambda
int main()
{
int a = 1;
int b = 2;
auto Swap = [=]() mutable
{
int tmp = a;
a = b;
b = tmp;
};
Swap();
cout << a << " " << b << endl;
return 0;
}
这里是=捕捉属于值传递给函数体,说明实际是交换不了a和b的,mutable,是为了解除捕捉过来的a,b的const属性。
int a = 1;
int b = 2;
auto Swap = [&]() mutable
{
int tmp = a;
a = b;
b = tmp;
};
Swap();
cout << a << " " << b << endl;
return 0;
这里是&捕捉给函数体使用是引用传递,可以交换a,b的值,这里可以不加mutable,因为引用类似于指针,初始是不带const属性的。