IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> C++ Lambda表达式是什么?如何使用? -> 正文阅读

[C++知识库]C++ Lambda表达式是什么?如何使用?

写咋前面:

lambda表达式百度百科简介:
Lambda 表达式(lambda expression)是一个匿名函数,Lambda表达式基于数学中的 λ 演算得名,直接对应于其中的lambda抽象(lambda abstraction),是一个匿名函数,即没有函数名的函数。Lambda表达式可以表示闭包(注意和数学传统意义上的不同)
闭就是封闭的意思(封闭就是其他地方都不调用它),包就是函数。
看完官方的一个简介还是不太懂这个东东,要明白每个语言可能对lambda表达式 – 匿名函数 的使用方式不太相同,但是其基本的思想都是一致的。

一、lambda表达式的优点

示例:举一个排序的例子

1.1 普通写法

#include<iostream>
#include<algorithm>//sort函数头文件
using namespace std;
bool compare(int& a, int& b)//比较方法 排升序
{
	return a > b;
}
int main()
{
	int a[] = { 1,2,3,4,5 };
	sort(a, a + 5, compare);
	for (int i = 0; i < 5; i++)
	{
		cout << a[i] << " ";
	}
	cout << endl;
	system("pause");
	return 0;
}

结果:
在这里插入图片描述

ps 这里补充一下 sort 函数的用法和参数列表

default (1)	
template <class RandomAccessIterator>
  void sort (RandomAccessIterator first, RandomAccessIterator last);
  //第一种用法传入需要排序的一段空间的 起 始 位置,默认是排升序
custom (2)	
template <class RandomAccessIterator, class Compare>
  void sort (RandomAccessIterator first, RandomAccessIterator last, Compare comp);
  //第三个参数可以是一个函数指针或者函数对象,该函数返回值会被转换为一个bool 类型,该函数接受范围中的两个元素作为参数,该参数就是为了自定义的类型或者自定义的一些比较方法来实现排序目的。

这里只是举一个例子,sort 函数有参数控制排升序还是降序,但是这只是适用于内置类型,当需要给自定义类型进行排序的时候就需要自己写一个比较的函数,但是每个自定义类型的都需要定义成函数的话会比较繁琐

1.2 使用 Lambda 表达式

int main()
{
	int a[] = { 1,2,3,4,5 };
	sort(a, a + 5, [](int& a, int& b) {return a > b; });//第三个参数为Lambda表达式
	for (int i = 0; i < 5; i++)
	{
		cout << a[i] << " ";
	}
	cout << endl;
	system("pause");
	return 0;
}

Lambda表达式

[](int& a, int& b) {return a > b; }

可以看到上述的函数调用只用了一行就搞定了,这就是Lambda表达式的好处 – 简洁
而且 使用匿名函数,可以免去函数的声明和定义。这样匿名函数仅在调用函数的时候才会创建函数对象,而调用结束后立即释放,所以匿名函数比非匿名函数更节省空间

二、Lambda 表达式定义

示例:[]() {};

#include<iostream>
using namespace std;
int main()
{
	[]() {};//最简单的一个Lambda 表达式写法
	system("pause");
	return 0;
}

是的,你没有看错,这样就是一个Lambda 表达式的写法,这样还能编译通过。
在这里插入图片描述
其实从上面的例子,大家也可以猜测出一些东西

[ ] 好吧这个暂时还猜不出来,猜下一个。
( ) 哎,这个我熟啊,这一看就是写参数的那个圆括号
{ ] 这个我更熟悉了,是写函数定义的花括号

2.1 lambda表达式语法

lambda表达式书写格式:[capture-list] (parameters) mutable -> return-type { statement }
好长一串,还都是英文,我来翻一下
lambda表达式书写格式:[捕获列表] (参数) 可变的-> 返回类型{ 陈述,声明 }

各部分说明:
1.[capture-list] : 捕捉列表,该列表总是出现在lambda函数的开始位置,编译器根据[ ]来判断接下来
的代码是否为lambda函数
,捕捉列表能够捕捉上下文中的变量供lambda函数使用
2.(parameters)参数列表。与普通函数的参数列表一致,如果不需要参数传递,则可以连同()一起
省略
3.mutable默认情况下,lambda函数总是一个const函数,mutable可以取消其常量性。使用该修
饰符时,参数列表不可省略(即使参数为空)。
4.->return-type返回值类型。用追踪返回类型形式声明函数的返回值类型,没有返回值时此部分
可省略。返回值类型明确情况下,也可省略,由编译器对返回类型进行推导。
5.{statement}函数体。在该函数体内,除了可以使用其参数外,还可以使用所有捕获到的变量。

注意:在lambda函数定义中,参数列表和返回值类型都是可选部分,而捕捉列表和函数体可以为空。
因此C++11中最简单的lambda函数为:[]{}; 该lambda函数不能做任何事情。

2.2 [ ] 捕获列表说明

捕捉列表 描述了上下文中那些数据可以被lambda使用,以及使用的方式传值还是传引用。

参数含义
[var]表示值传递方式捕捉变量var
[=]表示值传递方式捕获所有父作用域中的变量(包括this)
[&var]表示引用传递捕捉变量var
[&]表示引用传递捕捉所有父作用域中的变量(包括this)
[this]表示值传递方式捕捉当前的this指针

注意:

  1. 父作用域指包含lambda函数的语句块
  2. 语法上捕捉列表可由多个捕捉项组成,并以逗号分割
    比如:[=, &a, &b]:以引用传递的方式捕捉变量a和b,值传递方式捕捉其他所有变量 [&,a, this]:值
    传递方式捕捉变量a和this,引用方式捕捉其他变量 c. 捕捉列表不允许变量重复传递,否则就会导致编
    译错误。 比如:[=, a]:=已经以值传递方式捕捉了所有变量,捕捉a重复
  3. 在块作用域以外的lambda函数捕捉列表必须为空。
  4. 在块作用域中的lambda函数仅能捕捉父作用域中局部变量,捕捉任何非此作用域或者非局部变量
    会导致编译报错
  5. lambda表达式之间不能相互赋值,即使看起来类型相同
2.2.1 [ ] 表示什么值也不捕获,这样就访问不了外部的变量:

示例:

int main()
{
	int a = 9;
	[]() {cout << a << endl; };
	system("pause");
	return 0;
}

在这里插入图片描述

2.2.2 [ var ] 以值传递的方式捕捉变量 var

示例:

int main()
{
	int a = 9;
	auto lam = [a]() {cout << a << endl; };
	lam();
	return 0;
}

注意:这里直接写一个 a {cout << a << endl; }; 编译器是不会执行的,因为没人调用他,但是这里可以使用 auto 来推导并调用这个匿名函数

结果:
在这里插入图片描述

2.2.3 [& var] 表示引用传递捕捉变量 var

示例:

int main()
{
	int a = 9;
	auto lam = [&a]() {a = 10; cout << a << endl; };
	lam();
	return 0;
}

结果:
在这里插入图片描述
可以看到,传递引用在于Lambda 表达式内部可以对该值进行修改,当只是值传递捕获时,默认该值是 const 的 不能被修改,否则会报错
在这里插入图片描述

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

示例:

#include<iostream>
#include<string>
using namespace std;
int main()
{
	int a = 9;
	string s = "hello";
	auto lam = [=]() {cout << a << " "<<s<<endl; };
	lam();
	return 0;
}

在这里插入图片描述
同理默认是值传递,const 属性
但是要注意其传递的值的作用域
在这里插入图片描述

2.2.4 [ =,&var ] 表示值传递方式捕获所有父作用域中的变量,但是对变量var是引用传递捕获
2.2.5 [&, var] 以值捕获var, 但其余变量都靠引用捕获

示例:

#include<iostream>
#include<string>
using namespace std;
int main()
{
	int a = 9;
	string s = "hello";
	auto lam = [=, &a]() {a = 90; cout << a << " " << s << endl; };
	lam();
	auto lam1 = [&, a]() {s = "hhah"; cout << a << " " << s << endl; };
	lam1();
	return 0;
}

在这里插入图片描述

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-09-13 09:05:31  更:2021-09-13 09:07:14 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/19 20:51:10-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码