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的底层是通过仿函数来实现的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
学习并掌握C++2.0(11+14+17+20)的新特性,学习线程及线程池的应用 ---------------------------------------------------给小白学员的3年学习路径及计划技术方面分三块:1.纯开发技术方向2.音视频流媒体专业方向3.项目实战---------------------------------------------------1.纯开发技术方向(1) C++必须要过硬(至少学会10本经典好书)(2) 系统级编程(Windows、Linux),必须特别熟练系统API,灵活运用(3) 框架与工具(Qt、MFC):必须精通其中一种。(4) 架构与设计模式:需要提升一个高度,不再是简单的编码,而是思维模式。(5) 驱动级别(如果有兴趣,可以深入到驱动级:包括Windows、Linux)(6) 最好学习点Java+Html+javascript等WEB技术。2.音视频流媒体专业方向(1) 音视频流媒体基础理论:   必须认真学会,否则看代码就是看天书(2) 编解码方向:精通h.264,h.265(hevc), 包括理论和各个开源库(ffmpeg,libx264,libx265,...)。(3) 直播方向:  精通各种直播协议(rtsp,rtmp,hls,http-flv,...), 钻研各个开源库(live555,darwin,srs,zlmediakit,crtmpserver,...)(4) 视频监控:  理论+开源库(onvif+281818)(EasyMonitor、iSpy、ZoneMinder(web)、...) 3.项目实战(1) Qt项目:  至少要亲手练习10个实战项目(网络服务器、多线程、数据库、图像处理、多人聊天、等等)(2)音视频项目:包括编解码、视频监控、直播等各个方向,都需要亲手实战项目,包括视频服务器、后台管理系统、前端播放器(多端)---------------------------------------------------  第1章 C++11新特性 41). nullptr关键字与新语法 42). auto和decltype类型推导 6 auto讲解 6 auto示例 7 decltype 83). for区间迭代 94). 初始化列表 105). 模板增强 11外部模板 11类型别名模板 12默认模板参数 126). 构造函数 13委托构造 13继承构造 147). Lambda 表达式 158). 新增容器 20std::array 20std::forward_list 21无序容器 22元组 std::tuple 239). 正则表达式 2610). 语言级线程支持 28多线程库简介 2811). 右值引用和move语义 31右值引用和move语义 32转移左值 3412). constexpr 35第2章 C++14新特性 36Lambda 函数 36类型推导 37返回值类型推导(Return type deduction) 37泛型lambda 39[[弃用的]]  [[deprecated]]属性 40二进制数字和数字分隔符 41第3章 C++17新特性 42安装GCC10.2 42安装msys2-x86_64-20200720 42更新镜像 42更新软件库 43安装 MinGW64 等必要的软件 43环境变量Path 43编译命令 43constexpr 44typename 45折叠表达式 47结构化绑定 48条件分支语句初始化 49聚合初始化 50嵌套命名空间 52lambda表达式捕获*this的值 53改写/继承构造函数 54用auto作为非类型模板参数 55__has_include 56fallthrough 57nodiscard 57maybe_unused 58第4章 C++20新特性 59编译命令 59concept 59typename 60explicit 61constinit 62位域变量的默认成员初始化 62指定初始化 63基于范围的for循环初始化 64放宽基于范围的for循环,新增自定义范围方法 65嵌套内联命名空间 66允许用圆括弧的值进行聚合初始化 67unicode字符串字面量 68允许转换成未知边界的数组 68likely和unlikely 69第5章 C++2.0(11/14/17/20)总结与分析 705.1 C语言与C++ 715.2 语言可用性的强化 725.2.1 常量 725.2.2 变量及其初始化 735.2.3 类型推导 745.2.4 控制流 765.2.5 模板 775.2.6 面向对象 815.3 语言运行期的强化 835.3.1 Lambda 表达式 835.3.2 右值引用 865.4 容器 885.4.1 线性容器 885.4.2 无序容器 895.4.3 元组 895.5 智能指针与内存管理 905.5.1 RAII 与引用计数 905.5.2 std::shared_ptr 905.5.3 std::unique_ptr 915.5.4 std::weak_ptr 91第6章 C++2.0多线程原理与实战 93什么是并发 93并发的方式 93为什么使用并发 95线程简介 96创建线程的三种方式 971. 通过函数 972.通过类对象创建线程 993.通过lambda表达式创建线程 101thread线程的使用 101互斥量与临界区 105期物Future 111条件变量 112原子操作 114内存模型 118第7章 C++2.0线程池原理与实战 120线程与线程池的基本原理 1201)、线程 1202)、线程的生命周期 1213)、什么是单线程和多线程 1214)、线程池 1225)、四种常见的线程池 123线程池的架构与流程 123线程池代码实战 125    

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值