c++11——lambda表达式

以下是阿鲤对lambda表达式的学习总结,希望对大家有所帮助

一:lambda表达式的存在意义

二:lambda的语法

三:lambda的原理


一:lambda表达式的存在意义

在c++98中我们想要给一个自定义类型的数组进行排序,我们需要设计自己的排序规则,再将排序规则传入sort函数中,如下

#include<iostream>
#include<string>
#include<vector>
#include<algorithm>

using namespace std;

class student
{
	string m_name;
	string m_sex;
	int m_age;

public:

	student() = default;
	student(string name, string sex, int age):
		m_name(name),
		m_sex(sex),
		m_age(age)
	{}

	friend class compare;
};

class compare
{
public:
	bool operator()(student s1, student s2)
	{
		if (s1.m_age > s2.m_age)
		{
			return true;
		}
		else if(s1.m_age == s2.m_age)
		{
			if (s1.m_name > s2.m_name)
			{
				return true;
			}
		}
		else
		{
			return false;
		}
		return false;
	}
};

int main()
{
	vector<student> v;
	student s1("peter", "man", 18);
	student s2("peter", "female", 19);
	student s3("peter", "man", 20);

	v.push_back(s1);
	v.push_back(s2);
	v.push_back(s3);

	sort(v.begin(), v.end(), compare());

	return 0;
}

这样下来,我们每次为了比较就得写一个仿函数,这样就非常的麻烦,那么lambad表达式的出现就是来解决这个问题的。

二:lambda的语法

首先给出上面代码的lambda表达式

#include<iostream>
#include<string>
#include<vector>
#include<algorithm>

using namespace std;

class student
{
public:
	string m_name;
	string m_sex;
	int m_age;

	student() = default;
	student(string name, string sex, int age):
		m_name(name),
		m_sex(sex),
		m_age(age)
	{}

};

int main()
{
	vector<student> v;
	student s1("peter", "man", 18);
	student s2("peter", "female", 19);
	student s3("peter", "man", 20);

	v.push_back(s1);
	v.push_back(s2);
	v.push_back(s3);

	sort(v.begin(), v.end(), [](student &s1, student &s2)
								{
									if (s1.m_age > s2.m_age)
									{
										return true;
									}
									else if (s1.m_age == s2.m_age)
									{
										if (s1.m_name > s2.m_name)
										{
											return true;
										}
									}
									else
									{
										return false;
									}
									return false;
								}
	);

	return 0;
}

这样写下来是不是就感觉轻松了很多呢。

语法介绍:[capture-list](parameters)mutable->return-type{statement}

1:lambda表达式各部分说明

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

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

mutable:默认情况下,lambda函数总是一个const函数,加上mutable后可以取消其常量性。使用该修饰符时,参数列表不可以为空。

->return-type:返回值类型。用追踪返回类型的型式声明函数的返回值类型,没有返回值时此部分可省略。返回值类型明确时也可以省略。

{statement}:函数体。

注意:在lambda函数定义中,参数列表和返回值类型都是可选部分,而捕捉列表和函数体可以为空。比如:[]{}

2:捕捉列表说明:

捕捉列表描述了那些数据可以被捕捉,以及使用方式是值还是引用

[var]:表示以值传递的方式捕捉var

[=]:表示以值传递的方式捕获所有父作用域的变量(包括this)

[&var]:表示以引用捕捉var

[&]:表示以引用捕捉父作用域中的所有变量(包括this)

[this]:表示以值传递的方式捕捉当前的this指针

注意:

1:父作用域指包括lambda的语句块

2:语法上捕捉列表可由多个捕捉顶组成,并以逗号分隔

3:在块作用域以外的lambda函数捕捉列表必须为空

4:捕捉列表不允许重复传递

5:捕捉列表只能捕捉父作用域的局部变量

6:lambda之间不可以相互赋值

eg:

int m_d = 9;

int main()
{
	int a = 5;
	int b = 6;
	[] {};// 空的lambda表达式
	auto f1 = [a](int c) {c = a; };//以传值的方式:a不能改变值(比如a = 10的操作是违法的)
	auto f2 = [=](int c) {c = a + b + m_d; };//已传值的方式引入所有的父作用域变量
	auto f3 = [&]{a = 1, b = 2; };//传引用,可改
	auto f4 = [=, &a] {a = b + m_d; };//传值,只有a传引用
	auto f5 = [&, a] {b = a + m_d; };//传引用,只有a传值
	//auto f6 = [&, &a] {}//非法操作,不可重复同类型

	return 0;
}

三:lambda的原理

我们在前面讲到lambda表达式之间不可以相互赋值,那么这是为什么呢?下面我们将揭晓

#include<iostream>
using namespace std;

void(*pf)();
int m_d = 9;

int main()
{
	int a = 5;
	int b = 6;

	auto f1 = [] {cout << "hello eord" << endl; };
	auto f2 = [=](int c) {c = a + b + m_d; };
	
	pf = f1;//我们发现可以将lambda表达式赋值给同类型的函数指针
	//f2 = f1; 错误操作
	auto f3(f1);//但是却可以拷贝构造

	//我们打印一下f1,f2的类型
	cout << "f1 : " << typeid(f1).name() << endl;
	cout << "f2 : " << typeid(f2).name() << endl;
	cout << "f3 : " << typeid(f3).name() << endl;
	cout << "pf : " << typeid(pf).name() << endl;

	return 0;
}

运行结果:

我们发现f1,f2就是一个类,而f3则是拷贝了f1

然后我们看一下f1,f2的汇编代码

我们就会1发现,f1,f2的汇编代码和函数对象(仿函数)格式是一样的,这样我们就知道了lambda的底层是通过仿函数来实现的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值