【C++11】lambda表达式详解

news2024/11/16 7:50:07

目录

1.lambda引入

2.语法

3.捕捉列表详解

[ ]  不捕获任何外部变量

[=] 捕获父作用域的所有变量的值,只读不可以修改

[&]捕获父作用域的所有变量的引用,可修改捕获的变量

 [val] 只捕获指定的变量值,不可以修改

[&val] 只捕获外部变量val的引用

[this] 捕获当前类的this指针

 [=,&]混合 

4.mutable


1.lambda引入

在C++98中如想对数据集合中的数据进行排序,需要使用sort函数,该函数默认升序

#include <functional>
#include <algorithm>
int main()
{
	int arr[] = { 1,2,6,7,4,3,8 };
	sort(arr, arr + sizeof(arr) / sizeof(arr[0])); 
	for (auto& e : arr)
		cout << e;
	cout<<endl;
	sort(arr, arr + sizeof(arr) / sizeof(arr[0]),greater<int>());
	for (auto& e : arr)
		cout << e;
	return 0;
}

 但如果数据对象是自定义类型就需要用户自己写比较函数

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

class fruit
{
public:
	fruit(string name,int price,int num) :_name(name),_price(price),_num(num){}

	int _price;
	int _num;
	string _name;
};


struct ComparePriceLess
{
	bool operator()(const fruit& f1, const fruit& f2)
	{
		return f1._price < f2._price;
	}
};

struct ComparePriceGreater
{
	bool operator()(const fruit& f1, const fruit& f2)
	{
		return f1._price > f2._price;
	}
};
int main()
{
	vector<fruit> v = { { "苹果", 2, 5 }, { "香蕉", 3, 4 }, { "橙子", 2,3 }, { "菠萝", 1, 4 } };
	sort(v.begin(), v.end(), ComparePriceLess());
	for (auto& e : v)
		cout<<e._name;
	return 0;
}

2.语法

但是显然这样的方式每次都要今次那个不同功能的实现,自己手写实在不方便

引入lambda表达式:本质是一个含有operator()的匿名接口(或者类)

lambda的语法:

[capture list] (params list) mutable -> return type { function body }

capture list:捕捉列表,捕获的外部变量列表,可以为空,[ ]开头告诉编译器,现在要用lambda函数

params list:参数列表,与普通函数的形参列表是一样的,如果不需要传递参数,可以连()一起省略

mutable:lambda函数总是一个const函数,但是使用mutable可以取消其常性,使用它的时候,参数列表不能为空,即使参数为空

return type:返回值类型,用追踪返回类型形式声明函数的返回值类型,没有返回值的时候这部分可以省略,返回值类型明确的情况下也可以省略,由编译器对返回值类型推导

function body:函数体,在该函数体内,除了可以使用其参数外,还可以使用所有捕获到的变量。

 

在lambda中参数列表和返回值类型可以省略,但是捕捉列表和函数体是不能省略的,最简单的lambda函数是[ ]{ },该函数不能做任何事情

那么上面的比较函数可以用lambda函数表示成

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

class fruit
{
public:
	fruit(string name,int price,int num) :_name(name),_price(price),_num(num){}

	int _price;
	int _num;
	string _name;
};


struct ComparePriceLess
{
	bool operator()(const fruit& f1, const fruit& f2)
	{
		return f1._price < f2._price;
	}
};

struct ComparePriceGreater
{
	bool operator()(const fruit& f1, const fruit& f2)
	{
		return f1._price > f2._price;
	}
};
int main()
{
	vector<fruit> v = { { "苹果", 2, 5 }, { "香蕉", 3, 4 }, { "橙子", 2,3 }, { "菠萝", 1, 4 } };
	sort(v.begin(), v.end(), ComparePriceLess());
	for (auto& e : v)
		cout << e._name;
	cout << endl;
	sort(v.begin(), v.end(), [](const fruit& f1, const fruit& f2)
		{
			return f1._price < f2._price;
		});
	for (auto& e : v)
		cout<<e._name;
	return 0;
}

3.捕捉列表详解

下面所说的父作用域是指包含lambda函数的语句块

在块作用域以外的lambda函数捕捉列表必须为空
在块作用域中的lambda函数仅能捕捉父作用域中局部变量,捕捉任何非此作用域或者非局部变量都会导致编译报错
 

[ ]  不捕获任何外部变量

int main()
{
	int i = 1;
	auto func=[](int i) { cout << i << endl; };
	func(i);
	return 0;
}

[=] 捕获父作用域的所有变量的值,只读不可以修改

int main()
{
	int i = 1;
	auto func=[=]() { cout << i << endl; }; //没有形参 而是直接捕捉i
    func();
	return 0;
}

[&]捕获父作用域的所有变量的引用,可修改捕获的变量

int main()
{
	int i = 1;
	auto func=[&]() { cout << ++i << endl; };
	func();
	return 0;
}

 [val] 只捕获指定的变量值,不可以修改


int main()
{
	int i = 1,j = 2;
	auto func=[j]() { cout << i << endl; };
	func();
	return 0;
}

 报错是因为只捕获了j但是没有捕获i

[&val] 只捕获外部变量val的引用

[this] 捕获当前类的this指针

class fruit
{
public:
	fruit(int price) :_price(price) {}
	void Getprice()
	{
		cout << _price << endl;
	}
	void lambda()
	{
		auto func = [this]() {
			 this->Getprice();
		};
		func();
	}
private:
	int _price;
};

int main()
{
	fruit f(1);
	f.lambda();
}

 

 [=,&]混合 

一定要用,隔开,不允许重复捕捉比如[=,a] 这样会导致编译错误

int main()
{
	int i = 1,j = 2;
	auto func=[=,&j]() { cout << i <<" "<<++j << endl; };
	func();
	return 0;
}

综上可以看出lambda相当于一个无名函数,不能直接调用,但是可以用auto推演出类型然后赋给一个函数变量,调用该变量 

此外lambda表达式之间不能相互赋值,即使看起来类型是相同的

4.mutable

mutable关键字说明函数体中可以修改值捕捉的变量,但是不影响外部该变量的值,因为值传递是以拷贝方式实现的

int main()
{
	int i = 1,j = 2;
	auto func=[=,&j]()mutable { cout << ++i <<" "<<++j << endl; };
	func();
	cout << i << endl;
	return 0;
}

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/713085.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【云原生系列】云计算概念与架构设计介绍

1 什么是云计算 云计算是一种基于互联网的计算模式&#xff0c;在这个模式下&#xff0c;各种计算资源&#xff08;例如计算机、存储设备、网络设备、应用程序等&#xff09;可以通过互联网实现共享和交付。云计算架构设计的主要目标是实现高效、可扩展、可靠、安全和经济的计算…

读者与写者问题

本篇文章我们使用C探讨一下读者与写者问题. 1. 读者与写者问题引入 读写操作是计算机中对存储区最常见的两种操作. 我们之前探讨了生产者与消费者问题, 知道了如何开启多个线程, 现在就可以直接写出读者与写者问题的最基本的代码了, 仍从最简单的情况开始--两个读者, 代码如下…

React01-React简介及环境搭建

一、SPA 单页面应用 1. 多页面应用&#xff08;MPA&#xff09; 一个链接对应一个页面。 优点&#xff1a;便于百度搜索。 缺点&#xff1a;请求量大。 应用&#xff1a;电商网站 2. 单页面应用&#xff08;SPA&#xff09; 应用&#xff1a;音乐网站 优点&#xff1a;…

Babylist EDI 需求详解

Babylist 是一个为准父母提供方便和灵活的婴儿注册服务的平台&#xff0c;帮助他们准备迎接新生儿的到来。Babylist 与各种不同的品牌和零售商合作&#xff0c;包括婴儿用品、玩具、衣物和其他相关产品的制造商。用户可以在 Babylist 上浏览各种不同的产品&#xff0c;并根据自…

9、Redis集群(cluster)

是什么 Redis集群是一个提供在多个Redis节点间共享数据的程序集&#xff0c;Redis集群可以支持多个master 能干嘛 Redis集群支持多个master&#xff0c;每个master又可以挂载多个slave 读写分离 支持数据的高可用 支持海量数据的读写存储操作 由于Cluster自带Sentinel的故障转…

UWB智能定位管理系统源码(Java+ vue+ spring boot)

智能定位管理系统技术架构&#xff1a;Java vue spring boot 一、系统概述 系统聚焦基于UWB(超宽带)技术的底层定位网络和定位算法&#xff0c;通过对定位分站、定位标签、定位引擎的硏发&#xff0c;实现高精度定位网络&#xff0c;获取高精度定位结果&#xff0c;支撑行业大…

爬虫入门指南(6):反爬虫与高级技巧:IP代理、User-Agent伪装、Cookie绕过登录验证及验证码识别工具

文章目录 前言IP代理与User-Agent伪装IP代理User-Agent伪装 使用Cookie绕过登录验证使用验证码识别工具未完待续... 前言 随着互联网发展&#xff0c;网站数据变得越来越重要。然而&#xff0c;为了保护其数据的安全性和唯一性&#xff0c;网站通常会采取反爬虫措施。本篇博客将…

一场由AIGC引发的网文变革

文 | 螳螂观察 作者 | 青月 2019年底《庆余年》第一季播出引发了全民追剧热潮&#xff0c;不仅实现了国内的口碑、流量双丰收&#xff0c;还收获了包括韩国在内的27个国家或地区海外观众的超高评价。 经过三年多的蓄力&#xff0c;前不久《庆余年》第二季发布了开机特辑。这…

论文解读|CVPR 2023:非刚性点云匹配的神经内嵌算法

原创 | 文 BFT机器人 01 背景 在非刚性点云匹配领域&#xff0c;将两个或多个形状的点云对应起来是一个具有挑战性的任务。在这个问题中&#xff0c;形状的变形可能会导致点云之间的几何形状和拓扑结构的差异。因此&#xff0c;点云匹配方法需要能够识别和建立这些非刚性变形下…

一文图解|低精度定时器原理

Linux 内核通常会使用 定时器 来做一些延时的操作&#xff0c;比如常用的 sleep() 系统调用就是使用定时器来实现的。 在 Linux 内核中&#xff0c;有两种类型的定时器&#xff1a;高精度定时器 与 低精度定时器。低精度定时器基于硬件的时钟中断实现的&#xff0c;其定时周期…

开放式蓝牙耳机推荐,高性价比的蓝牙耳机首选这些品牌

在开放式耳机的流行度越来越高的同时&#xff0c;新接触想入手开放式耳机的小伙伴们&#xff0c;面对不同样式型号的耳机&#xff0c;会更多的考虑舒适度还是音质&#xff1f;亦或者是外观呢&#xff0c;通过各方体验调查&#xff0c;我总结了几款值得大家选择的开放式耳机&…

Linux--共同访问的公共目录不允许a用户删除b用户目录或文件:粘滞位 -t

情景&#xff1a; ①当多个用户共享同一个目录&#xff0c;需要在该目录下&#xff0c;进行读写、创建文件 ②但是自己只能删除自己的&#xff0c;而不能删除别人的&#xff08;w:可以互删的&#xff0c;但是不满足条件&#xff09; 语法&#xff1a; chmod t 目录名 注意…

CICD集合(一):Jenkins2.3.46安装

一、安装和安装Jenkins 0.前提 因jenkins从2.357版本开始不再支持java8 2、jenkins与java版本对应查看&#xff0c;与jenkins下载&#xff1a;Redhat Jenkins Packages 3、打算使用java8&#xff0c;所以选择安装2.346.3-1.1 4、安装jenkins之前&#xff0c;安装好java8并…

前后端免费学 | 第六届字节跳动青训营报名啦

线上活动&#xff0c;全程免费 报名时间&#xff1a;2023年6月2日 - 2023年7月10日 报名地址&#xff1a;点我报名&#xff0c;暑假一起学技术呀... 前言 其实去年我就想参加青训营的&#xff0c;但是那时的我刚转完专业&#xff0c;觉得自己太菜了&#xff0c;单方面认为自己…

MySQL 8 group by 报错 this is incompatible with sql_mode=only_full_group_by

根据错误信息大概知道&#xff0c;是sql_mode参数设置为only_full_group_by的不兼容&#xff0c;如果select 的字段不在 group by 中&#xff0c;并且select 字段没有使用聚合函数&#xff08;SUM,MAX等&#xff09;&#xff0c;这个sql查询是被mysql认为非法的&#xff0c;会报…

easyui datagrid合并单元格

表头合并 columns:[[{field:bigarea,title:大区,rowspan:2,width:$$.fillsize(0.1),align:center},{field:ProvinceName,title:省份,rowspan:2,width:$$.fillsize(0.1),align:center},{field:dbct_name,title:分拨中心,rowspan:2,width:$$.fillsize(0.1),align:center},{field…

IDEA新建Spring Boot项目

新建项目之前已经将JDK环境变量啥的都安装好了&#xff0c;本文只有新建。 1.打开idea&#xff0c;选择Create New Project。如果已经打开其他项目&#xff0c;点击File->New->Project&#xff0c;也可以打开新建的界面。 2.点左侧的Spring Initializr然后如图&#xff…

三款新品齐发:大势智慧刷新实景三维技术新高度

近日&#xff0c;大势智慧“海量数据轻量化技术与新品夏季发布会”在大势智慧武汉总部盛大举行&#xff0c;并同步在其官方微信视频号进行线上直播&#xff0c;线上线下双会场气氛热烈、互动频繁、精彩纷呈。在此次发布会上&#xff0c;大势智慧集中推出轻量化技术、大势速影、…

第1章 Java概述

目录 1 Java相关1.1 跨平台性的体现1.2 Java的运行机制1.3 JDK、JRE、JVM及其关系1.4 Java注释 2 其他2.1 转义字符2.2 常用Dos命令2.3 相对路径与绝对路径 3 思维导图 上图为思维导图 1 Java相关 1.1 跨平台性的体现 Java的跨平台性&#xff1a;程序员编写的Java程序可以在不…

MyBatis介绍与下载

目录 MyBatis 介绍 MyBatis 主要特点 MyBatis 下载 IDEA创建maven项目&#xff08;默认&#xff09; MyBatis 介绍 MyBatis是一种开源的Java持久化框架&#xff0c;用于将SQL数据库访问和映射任务与Java对象之间的映射分离。它提供了一种简单的方式来对数据库进行操作&…