C++11——lambda表达式-CSDN博客

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

在这里插入图片描述

文章目录

1. C++98对自定义类型的排序

在C++98中想要对自定义类型就行排序我们得自己写仿函数来表明我们相对哪一项进行排序

struct Student
{
	Student(string name, long id, double score)
		:_name(name)
		,_id(id)
		,_score(score)
	{}

	string _name;
	long _id;
	double _score;
};

//按名字排序 -- 降序
struct CmpName
{
	bool operator()(const Student& stu1, const Student& stu2)
	{
		return stu1._name < stu2._name;
	}
};
//按学号排序 -- 降序
struct CmpId
{
	bool operator()(const Student& stu1, const Student& stu2)
	{
		return stu1._id < stu2._id;
	}
};
//按分数排序 -- 降序
struct CmpScore
{
	bool operator()(const Student& stu1, const Student& stu2)
	{
		return stu1._score < stu2._score;
	}
};

int main()
{
	vector<Student> v = { {"张三",101,99.3},{"李四",104,85.2},{"王五",102,99.9} };
	sort(v.begin(), v.end(),CmpName());

	sort(v.begin(), v.end(),CmpId());
	
	sort(v.begin(), v.end(),CmpScore());

	return 0;
}

如果代码风格较好然后加上了注释这其他人一看就懂是什么意思。但如果命名不规范就是个很头疼的问题。

例如

int main()
{
	vector<Student> v = { {"张三",101,99.3},{"李四",104,85.2},{"王五",102,99.9} };
	sort(v.begin(), v.end(),Cmp1());

	sort(v.begin(), v.end(),Cmp2());
	
	sort(v.begin(), v.end(),Cmp3());

	return 0;
}

这里的仿函数我们看到就不知道是对哪一项进行排序就得往前翻如果前面的命名也不规范那就十分痛苦。

而且一旦我们的对象的参数多了那我们就得写出对应的仿函数这不是很方便于是在C++11中出现了lambda表达式

2. lambda表达式语法

lambda表达式格式[capture-list] (parameters) mutable -> return-type { statement }

示例[] (int x,int y)->int { return x+y;}

  • lambda表达式各部分说明

    []捕捉列表该列表总是出现在lambda函数的开始位置编译器根据[]来 判断接下来的代码是否为lambda函数捕捉列表能够捕捉上下文中的变量供lambda函数使用。

    ()参数列表。与普通函数的参数列表一致如果不需要参数传递则可以 连同()一起省略。

    mutable默认情况下lambda函数总是一个const函数mutable可以取消其常量性。使用该修饰符时参数列表不可省略(即使参数为空)。

    ->returntype返回值类型。用追踪返回类型形式声明函数的返回值类型没有返回值时此部分可省略返回值类型明确情况下也可省略由编译器对返回类型进行推导

    {statement}函数体。在该函数体内除了可以使用其参数外还可以使用所有捕获到的变量。

int main()
{
	vector<Student> v = { {"张三",101,99.3},{"李四",104,85.2},{"王五",102,99.9} };
	sort(v.begin(), v.end(), [](const Student& stu1, const Student& stu2)->bool {return stu1._name < stu2._name; });

	sort(v.begin(), v.end(), [](const Student& stu1, const Student& stu2)->bool {return stu1._id < stu2._id; });
	
	sort(v.begin(), v.end(), [](const Student& stu1, const Student& stu2)->bool {return stu1._score < stu2._score; });

	return 0;
}

2.1 捕捉列表

  • [var]表示值传递方式捕捉变量var

    int a = 1;
    int b = 2;
    double rate = 2.5;
    auto f1 = [rate](int x, int y) {return x + y; };
    cout<<f1(a,b)<<endl;	//输出 7.5
    
  • [&var]表示引用传递捕捉变量var

    适用于对象较大或者需要修改捕捉列表里面的值

    int a = 1;
    int b = 2;
    auto swap1 = [a, b]() mutable {
        //mutable让捕捉的a b可以修改
        //但这里面的a b 属于是外面a b的拷贝
        int tmp = a;
        a = b;
        b = tmp;
    };
    swap1();
    
    
    auto swap2 = [&a, &b] {
        //捕捉引用可以直接修改外面a b的值了
        int tmp = a;
        a = b;
        b = tmp;
    };
    swap2();
    
  • [=]表示值传递方式捕获所有父作用域中的变量(包括this)

    捕捉所有的外部变量

    int a = 1;
    int b = 2;
    int c = 3;
    auto f2 = [=]() {
        cout << a << " " << b << " " << c << " " << endl;
    };
    f2();
    
  • [&]表示引用传递捕捉所有父作用域中的变量(包括this)

    捕捉所有外部变量的引用

    int a = 1;
    int b = 2;
    int c = 3;	
    auto f3 = [&]() {
    cout << ++a << " " << ++b << " " << ++c << " " << endl;
    };
    f3();
    cout << a << " " << b << " " << c << " " << endl;
    //也可以混合捕捉,这里的a就是不可修改的了普通捕捉
    auto f4 = [&, a] {
    cout << a << " " << ++b << " " << ++c << " " << endl;
    };
    cout << a << " " << b << " " << c << " " << endl;
    
  • [this]表示值传递方式捕捉当前的this指针

3. lambda底层原理

int main()
{
	auto f1 = [](int x, int y) {return x + y; };
	auto f2 = [](int x, int y) {return x + y; };
	//f1 = f2;	//error
	cout << typeid(f1).name() << endl;
	cout << typeid(f2).name() << endl;
	return 0;
}

这段代码运行之后发现f1f2的类型是

image-20231018120622477

这里lambda的底层就是一个仿函数就和范围的for的底层就是迭代器一样上层将其封装了调用的就是类的operator()

image-20231018121051482

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6
标签: c++