lmabda表达式
问题:c++98中对自定义类型进行排序时,需要自己写仿函数实现比较逻辑,并传递给sort库函数进行排序十分不便,于是c++11提供了一个新的玩法即lambda表达式
//有lambda表达式前
struct Goods
{
string _name; // 名字
double _price; // 价格
int _evaluate; // 评价
Goods(const char* str, double price, int evaluate)
:_name(str)
, _price(price)
, _evaluate(evaluate)
{}
};
//实现小比较逻辑的仿函数
struct ComparePriceLess
{
bool operator()(const Goods& gl, const Goods& gr)
{
return gl._price < gr._price;
}
};
//实现小比较逻辑的仿函数
struct ComparePriceGreater
{
bool operator()(const Goods& gl, const Goods& gr)
{
return gl._price > gr._price;
}
};
int main()
{
vector<Goods> v = { { "苹果", 2.1, 5 }, { "香蕉", 3, 4 }, { "橙子", 2.2,
3 }, { "菠萝", 1.5, 4 } };
sort(v.begin(), v.end(), ComparePriceLess());
sort(v.begin(), v.end(), ComparePriceGreater());
}
//有lambda表达式后
struct Goods
{
string _name; // 名字
double _price; // 价格
int _evaluate; // 评价
Goods(const char* str, double price, int evaluate)
:_name(str)
, _price(price)
, _evaluate(evaluate)
{}
};
vector<Goods> v = { { "苹果", 2.1, 5 }, { "香蕉", 3, 4 }, { "橙子", 2.2, 3 }, { "菠萝", 1.5, 4 } };
sort(v.begin(), v.end(), [](Goods g1, Goods g2)->bool
{return g1._price < g2._price; });//按照价格升序
sort(v.begin(), v.end(), [](Goods g1, Goods g2)->bool
{return g1._price > g2._price; });//按照价格降序
sort(v.begin(), v.end(), [](Goods g1, Goods g2)->bool
{return g1._evaluate < g2._evaluate; });//按照评价升序
sort(v.begin(), v.end(), [](Goods g1, Goods g2)->bool
{return g1._evaluate > g2._evaluate; });//按照评价降序
格式:
[capture list] (parameters) mutable -> return_type {
statement
}
A == 捕捉列表, B == 参数列表, C == 返回值
[A] (B)-> C {函数体}
- [capture list]:捕捉列表,编译器也会根据[]判断接下来的代码是不是lambda函数,它用于捕获所在作用域的变量供lambda函数使用
- (parameters):参数列表,与普通含糊的参数列表一致,如果不需要传参可以连带()一起省略
- mutable :默认情况下,lambda函数默认是const函数,mutable可以取消其常量性,使用该修饰符时,参数列表即使为空也不可省略
- return_type:返回值类型,没有返回值或者返回值类型明确都可以省略返回值,编译器会对返回值类型进行推导
- statement:函数体,在该函数体内除了可以使用参数列表中的参数外,还可以使用所有捕获到的变量
注意事项:
1、lambda函数的参数列表和返回值类型都是依据需求可有可无的,捕捉列表和函数体可以为空,因此c++11中最简单的lambda函数为[]{},该lambda函数不能做任何事情
2、lambda表达式的捕捉列表[]也可以捕捉父作用域中的变量供自己使用,捕捉的方式分为值捕捉和引用捕捉,且捕捉队列可以由多个捕捉项组成,并以逗号分割:
- [var]:以值传递方式捕捉指定变量var
- [=]:以值传递的方式捕获所有父作用域中的所有变量(包括this)
- [&var]:以引用传递的方式捕捉指定变量var
- [&]:以引用传递的方式捕捉父作用域中的所有变量(包括this)
- [this]:以值传递的方式捕捉当前的this指针
int a = 10;
char* b = "xxxxxxxxxxx"
vector<double> v{1.11,2.22};
auto it = [a,&b,c]()->bool{return b+="abcd";};
//以值传递的方式捕捉a和c,引用捕捉b
3、lambda表达式间不能互相赋值,即使看起来类型相同
4、捕捉列表不允许重复传递,否则编译报错
[=,a]
=已经以值传递的方式捕捉了所有变量,再以值传递的方式捕捉a变量造成重复捕捉,编译报错
结论:底层上编译器在遇到lambda表达式时,会自动生成一个类,在该类中重载operator()(编译器在处理Lambda表达式时,会生成一个匿名的闭包类(closure class),这个闭包类中会包含Lambda表达式的函数调用运算符operator()
的重载。这个闭包类被用来表示Lambda表达式,并且在运行时可以像函数对象一样被调用)
#include <iostream>
int main() {
int x = 10;
int y = 5;
auto lambda = [x, y] () {
return x + y;
};
std::cout << "Result: " << lambda() << std::endl;
return 0;
}
class __lambda_12345 {
private:
int x;
int y;
public:
__lambda_12345(int x, int y) : x(x), y(y) {}
int operator()() {
return x + y;
}
};
~over~