lmabda表达式

发布于:2024-05-18 ⋅ 阅读:(84) ⋅ 点赞:(0)

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~