C++——C++11第二篇
目录
可变参数模板
lambda表达式
lambda表达式语法
捕获列表说明
可变参数模板
可变参数:可以有0到n个参数,如之前学过的 Printf
C++11的新特性可变参数模板能够让您创建可以接受可变参数的函数模板和类模板
模板参数包
// Args是一个模板参数包,args是一个函数形参参数包
// 声明一个参数包Args...args,这个参数包中可以包含0到任意个模板参数。
template <class ...Args>
void ShowList(Args... args)
{}
上面的参数args前面有省略号,所以它就是一个可变模版参数,我们把带省略号的参数称为“参数
包”,它里面包含了0到N(N>=0)个模版参数。我们无法直接获取参数包args中的每个参数的,
只能通过展开参数包的方式来获取参数包中的每个参数,这是使用可变模版参数的一个主要特
点,也是最大的难点,即如何展开可变模版参数。由于语法不支持使用args[i]这样方式获取可变
参数,所以我们的用一些奇招来一一获取参数包的值
传参时,参数个数没有限制
当没有val参数时,如何查看参数包内容
逗号表达式展开参数包
这种展开参数包的方式,不需要通过递归终止函数,是直接在expand函数体中展开的, printarg
不是一个递归终止函数,只是一个处理参数包中每一个参数的函数。这种就地展开参数包的方式
实现的关键是逗号表达式。我们知道逗号表达式会按顺序执行逗号前面的表达式。
expand函数中的逗号表达式:(printarg(args), 0),也是按照这个执行顺序,先执行
printarg(args),再得到逗号表达式的结果0。同时还用到了C++11的另外一个特性——初始化列
表,通过初始化列表来初始化一个变长数组, {(printarg(args), 0)...}将会展开成((printarg(arg1),0),
(printarg(arg2),0), (printarg(arg3),0), etc... ),最终会创建一个元素值都为0的数组int arr[sizeof...
(Args)]。由于是逗号表达式,在创建数组的过程中会先执行逗号表达式前面的部分printarg(args)
打印出参数,也就是说在构造int数组的过程中就将参数包展开了,这个数组的目的纯粹是为了在
数组构造的过程展开参数包
也可以这样
vector中有可变参数包
push_back不能像红框那样传参,必须make_pair
区别:push_back要先构造pair对象(构造+拷贝构造/移动构造),emplace_back和push_back一样
而对于listpush_back和emplace_back不一样,emplace_back没有拷贝构造
写一个日期类
g++下vector的push_back和emplace_back仍然没有区别,而list仍然有区别
lambda表达式
像函数一样使用的对象/类型
1.函数指针 2.仿函数/函数对象 3.lambda
如果待排序元素为自定义类型,需要用户定义排序时的比较规则:
struct Goods
{
string _name; // 名字
double _price; // 价格
int _evaluate; // 评价
Goods(const char* str, double price, int evaluate)
:_name(str)
, _price(price)
, _evaluate(evaluate)
{}
};
struct ComparePriceLess
{
bool operator()(const Goods& gl, const Goods& gr)
{
return gl._price < gr._price;
}
};
struct ComparePriceGreater
{
bool operator()(const Goods& gl, const Goods& gr)
{
return gl._price > gr._price;
}
};
int main()
{
vector<Goods> v = { { "苹果", 2.1, 5 }, { "香蕉", 3, 4 }, { "橙子", 2.2,
3 }, { "菠萝", 1.5, 4 } };
sort(v.begin(), v.end(), ComparePriceLess());
sort(v.begin(), v.end(), ComparePriceGreater());
}
上面这种排序比较麻烦,需要写多个排序函数 ,用lambda对上面的排序进行优化
lambda表达式语法
lambda表达式书写格式:[capture-list] (parameters) mutable -> return-type { statement
}
1. lambda表达式各部分说明
[capture-list] : 捕捉列表,该列表总是出现在lambda函数的开始位置,编译器根据[]来
判断接下来的代码是否为lambda函数,捕捉列表能够捕捉上下文中的变量供lambda
函数使用。
(parameters):参数列表。与普通函数的参数列表一致,如果不需要参数传递,则可以
连同()一起省略
mutable:默认情况下,lambda函数总是一个const函数,mutable可以取消其常量
性。使用该修饰符时,参数列表不可省略(即使参数为空)。
->returntype:返回值类型。用追踪返回类型形式声明函数的返回值类型,没有返回
值时此部分可省略。返回值类型明确情况下,也可省略,由编译器对返回类型进行推
导。
{statement}:函数体。在该函数体内,除了可以使用其参数外,还可以使用所有捕获
到的变量。
注意:
在lambda函数定义中,参数列表和返回值类型都是可选部分,而捕捉列表和函数体可以为
空。因此C++11中最简单的lambda函数为:[]{}; 该lambda函数不能做任何事情。 {}里写的语句较多
如果不传参数进行x和y交换,使用捕捉列表,但是默认捕捉的对象不能修改
加了moutable之后程序能运行,但是结果不对
捕获列表说明
捕捉列表描述了上下文中那些数据可以被lambda使用,以及使用的方式传值还是传引用。
[var]:表示值传递方式捕捉变量var
[=]:表示值传递方式捕获所有父作用域中的变量(包括this)
[&var]:表示引用传递捕捉变量var
[&]:表示引用传递捕捉所有父作用域中的变量(包括this)
[this]:表示值传递方式捕捉当前的this指针
注意:
a. 父作用域指包含lambda函数的语句块
b. 语法上捕捉列表可由多个捕捉项组成,并以逗号分割。
比如:[=, &a, &b]:以引用传递的方式捕捉变量a和b,值传递方式捕捉其他所有变量
[&,a, this]:值传递方式捕捉变量a和this,引用方式捕捉其他变量
c. 捕捉列表不允许变量重复传递,否则就会导致编译错误。
比如:[=, a]:=已经以值传递方式捕捉了所有变量,捕捉a重复
d. 在块作用域以外的lambda函数捕捉列表必须为空。
e. 在块作用域中的lambda函数仅能捕捉父作用域中局部变量,捕捉任何非此作用域或者
非局部变量都
会导致编译报错。
f. lambda表达式之间不能相互赋值,即使看起来类型相同
此时结果正确
之前的问题就能得到解决,就不需要些那么多的比较函数
这种情况什么都不打印
这是匿名函数对象 lambda的定义,而我们没有调用它,所以什么都不打印
不允许这种写法,上面有解释过 c. 捕捉列表不允许变量重复传递,否则就会导致编译错误。
比如:[=, a]:=已经以值传递方式捕捉了所有变量,捕捉a重复
这种写法也会报错,其余都是引用捕捉,a传值捕捉,捕捉后进行a++会报错
但这样可以,不对a进行操作
lambda父作用域,父作用域是当前所在的函数(栈帧)
f不在当前栈帧,但能编译成功。这是因为全局变量不在栈帧中,在静态区,哪个位置都可以对他进行使用
当我们把abcde写到其它函数进行捕捉,此时会报错
捕捉列表的本质就是在传参
lambda底层实际是一个仿函数
class Rate
{
public:
Rate(double rate): _rate(rate)
{}
double operator()(double money, int year)
{ return money * _rate * year;}
private:
double _rate;
};
int main()
{
// 函数对象
double rate = 0.49;
Rate r1(rate);
r1(10000, 2);
// lamber
auto r2 = [=](double monty, int year)->double{return monty*rate*year;
};
r2(10000, 2);
return 0;
}
从使用方式上来看,函数对象与lambda表达式完全一样。
函数对象将rate作为其成员变量,在定义对象时给出初始值即可,lambda表达式通过捕获列表可
以直接将该变量捕获到。
实际在底层编译器对于lambda表达式的处理方式,完全就是按照函数对象的方式处理的,即:如
果定义了一个lambda表达式,编译器会自动生成一个类,在该类中重载了operator()。
lambda表达式之间不能相互赋值,即使看起来类型相同
不能互相赋值是因为这是俩个lambda,俩个lambda的uuid(上面汇编<lambda:后面的字符串>)不一样,相当于这俩个lambda属于俩个类型,但是可以将lambda表达式赋给函数指针。
void (*PF)();
int main()
{
auto f1 = []{cout << "hello world" << endl; };
auto f2 = []{cout << "hello world" << endl; };
//f1 = f2; // 编译失败--->提示找不到operator=()
// 允许使用一个lambda表达式拷贝构造一个新的副本
auto f3(f2);
f3();
// 可以将lambda表达式赋值给相同类型的函数指针
PF = f2;
PF();
return 0;
}
相关文章:

C++——C++11第二篇
目录 可变参数模板 lambda表达式 lambda表达式语法 捕获列表说明 可变参数模板 可变参数:可以有0到n个参数,如之前学过的 Printf C11的新特性可变参数模板能够让您创建可以接受可变参数的函数模板和类模板 模板参数包 // Args是一个模板参数包&…...
14.最长公共前缀
编写一个函数来查找字符串数组中的最长公共前缀。如果不存在公共前缀,返回空字符串 ""。示例 1:输入:strs ["flower","flow","flight"]输出:"fl"示例 2:输入&…...

【免费教程】 SWMM在城市水环境治理中的应用及案例分析
SWMMSWMM(storm water management model,暴雨洪水管理模型)是一个动态的降水-径流模拟模型,主要用于模拟城市某一单一降水事件或长期的水量和水质模拟。EPA(Environmental Protection Agency,环境保护署&am…...

SortableJS/Sortable拖拽组件,使用详细(Sortablejs安装使用)
简述 作为一名前端开发人员,在工作中难免会遇到拖拽功能,分享一个github上一个不错的拖拽js库,能满足我们在项目开发中的需要,支持Vue和React,下面是SortableJS的使用详细; 这个是sortableJS中文官方文档&…...
Heartbeat+Nginx实验
HeartbeatNginx实验 Heartbeat是什么? Heartbeat是 Linux-HA 工程的一个组件,自1999 年开始到现在,发布了众多版本,是目前开源 Linux-HA项 目成功的一个例子,在行业内得到了广泛的应用 构建规划: 两台后…...

JavaEE|网络编程之套接字 TCP
文章目录一、ServerSocket API构造方法常用方法二、Socket API构造方法常用方法注意事项三、TCP中的长短连接E1:一发一收(短连接)E2:请求响应(短连接)E3:多线程下的TCP回响服务器说明:这部分说实话有点懵&a…...

Robot Framework自动化测试---元素定位
不要误认为Robot framework 只是个web UI测试工具,更正确的理解Robot framework是个测试框架,之所以可以拿来做web UI层的自动化是国为我们加入了selenium2的API。比如笔者所处工作中,更多的是拿Robot framework来做数据库的接口测试…...
ASP.NET Core中的路由
传统路由 app.MapControllerRoute( name: "default", pattern: "{controllerHome}/{actionIndex}/{id?}"); MapControllerRoute用于创建单个路由。 单个路由命名为 default 路由 。大多数具有控制器和视图的应用都使用类似 default 路由的路由模板。 之所…...

VBA提高篇_26 Textbox多行_ListBox_ComboBox
文章目录1. 文本框多行换行2. ListBox: 列表框2.1 列表框中添加条目的三种方法:3. ComboBox 组合框: 属性方法等同于以上ListBox1. 文本框多行换行 MultiLine: 控制文本框多行自动换行() Enterkeybehevior: True 代表允许在文本框中使用回车键换行 WordWrap: True 代表自动换…...

python环境配置
python环境配置一、ADB环境配置1、ADB下载路径:2、点击下载3、解压并放到本地磁盘4、配置ADB环境变量二、Python环境配置1、Python下载路径:2、点击下载(默认下载最新的)3、解压并放到本地磁盘4、配置Python环境变量5、配置pip环境变量三、Pycharm安装1、pycharm下载路径:2、点…...

集算器连接外部库
1. 配置jar包将以下jar包从报表的类路径(【安装根目录】\report\lib或【安装根目录】\report\web\webapps\demo\WEB-INF\lib)中拷贝到集算器目录(【安装根目录】\esProc\ extlib\mongoCli);润乾外部库核心jar为:scu-mo…...

力扣刷题|216.组合总和 III、17.电话号码的字母组合
文章目录LeetCode 216.组合总和题目链接🔗思路LeetCode 17.电话号码的字母组合题目链接🔗思路LeetCode 216.组合总和 题目链接🔗 LeetCode 216.组合总和 思路 本题就是在[1,2,3,4,5,6,7,8,9]这个集合中找到和为n的k个数的组合。 相对于7…...

机器学习笔记之谱聚类(一)k-Means聚类算法介绍
机器学习笔记之谱聚类——K-Means聚类算法介绍引言回顾:高斯混合模型聚类任务基本介绍距离计算k-Means\text{k-Means}k-Means算法介绍k-Means\text{k-Means}k-Means算法示例k-Means\text{k-Means}k-Means算法与高斯混合模型的关系k-Means\text{k-Means}k-Means算法的…...

云原生周刊 | 2023 年热门:云 IDE、Web Assembly 和 SBOM | 2023-02-20
在 CloudNative SecurityCon 上,云原生计算基金会的首席技术官 Chris Aniszczyk 在 The New Stack Makers 播客的这一集中强调了 2023 年正在形成几个趋势: 随着 GitHub 的 Codespaces 平台通过集成到 GitHub 服务中获得认可,云 IDE…...

python 打包EXE
注: 从个人博客园 移植而来 环境: Windows7 Python 2.7 参考: 使用pyinstaller打包python程序 Pyinstaller 打包发布经验总结 Using PyInstaller 简介 使用python引用第三方的各种模块编写一个工具后,如果想发给其他人&…...

CANopen概念总结、心得体会
NMT网络管理报文: NMT 主机和 NMT 从机之间通讯的报文就称为 NMT 网络管理报文。常见报文说明: 0101---------------网络报文发送Nmt_Start_Node,让电机进入OP模式(此时还不会发送同步信号) setState(d, Operational)------------------开启…...

【2】MYSQL数据的导入与导出
文章目录 MYSQL-库(相同库名称)的导入导出MYSQL-库(不同库名称)的导入导出MYSQL-表的导入导出MYSQL-表的指定查询记录导入导出前提: 客户端工具是:SQLyog MYSQL-库(相同库名称)的导入导出 1、选中指定库——右键,选择【将数据库复制到不同的主机/数据库】 2、选中指…...

Kaggle系列之CIFAR-10图像识别分类(残差网络模型ResNet-18)
CIFAR-10数据集在计算机视觉领域是一个很重要的数据集,很有必要去熟悉它,我们来到Kaggle站点,进入到比赛页面:https://www.kaggle.com/competitions/cifar-10CIFAR-10是8000万小图像数据集的一个子集,由60000张32x32彩…...

ESP-C3入门11. 创建最基本的HTTP请求
ESP-C3入门11. 创建最基本的HTTP请求一、menuconfig配置二、配置 CMakeLists1. 设置项目的额外组件目录2. 设置头文件搜索目录三、在 ESP32 上执行 HTTP 请求的基本步骤1. 创建 TCP 连接2. 设置 HTTP 请求3. 发送 HTTP 请求4. 接收 HTTP 响应5. 处理 HTTP 响应6. 关闭 TCP 连接…...

K8S+Jenkins+Harbor+Docker+gitlab集群部署
K8SJenkinsHarborDockergitlab服务器集群部署 目录K8SJenkinsHarborDockergitlab服务器集群部署1.准备以下服务器2.所有服务器统一处理执行2.1 关闭防火墙2.2 关闭selinux2.3 关闭swap(k8s禁止虚拟内存以提高性能)2.4 更新yum (看需要更新)2.5 时间同步2…...

HTML 列表、表格、表单
1 列表标签 作用:布局内容排列整齐的区域 列表分类:无序列表、有序列表、定义列表。 例如: 1.1 无序列表 标签:ul 嵌套 li,ul是无序列表,li是列表条目。 注意事项: ul 标签里面只能包裹 li…...

ESP32 I2S音频总线学习笔记(四): INMP441采集音频并实时播放
简介 前面两期文章我们介绍了I2S的读取和写入,一个是通过INMP441麦克风模块采集音频,一个是通过PCM5102A模块播放音频,那如果我们将两者结合起来,将麦克风采集到的音频通过PCM5102A播放,是不是就可以做一个扩音器了呢…...
Robots.txt 文件
什么是robots.txt? robots.txt 是一个位于网站根目录下的文本文件(如:https://example.com/robots.txt),它用于指导网络爬虫(如搜索引擎的蜘蛛程序)如何抓取该网站的内容。这个文件遵循 Robots…...

Mac下Android Studio扫描根目录卡死问题记录
环境信息 操作系统: macOS 15.5 (Apple M2芯片)Android Studio版本: Meerkat Feature Drop | 2024.3.2 Patch 1 (Build #AI-243.26053.27.2432.13536105, 2025年5月22日构建) 问题现象 在项目开发过程中,提示一个依赖外部头文件的cpp源文件需要同步,点…...

Linux --进程控制
本文从以下五个方面来初步认识进程控制: 目录 进程创建 进程终止 进程等待 进程替换 模拟实现一个微型shell 进程创建 在Linux系统中我们可以在一个进程使用系统调用fork()来创建子进程,创建出来的进程就是子进程,原来的进程为父进程。…...
React---day11
14.4 react-redux第三方库 提供connect、thunk之类的函数 以获取一个banner数据为例子 store: 我们在使用异步的时候理应是要使用中间件的,但是configureStore 已经自动集成了 redux-thunk,注意action里面要返回函数 import { configureS…...

2025年渗透测试面试题总结-腾讯[实习]科恩实验室-安全工程师(题目+回答)
安全领域各种资源,学习文档,以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各种好玩的项目及好用的工具,欢迎关注。 目录 腾讯[实习]科恩实验室-安全工程师 一、网络与协议 1. TCP三次握手 2. SYN扫描原理 3. HTTPS证书机制 二…...
Qt 事件处理中 return 的深入解析
Qt 事件处理中 return 的深入解析 在 Qt 事件处理中,return 语句的使用是另一个关键概念,它与 event->accept()/event->ignore() 密切相关但作用不同。让我们详细分析一下它们之间的关系和工作原理。 核心区别:不同层级的事件处理 方…...
GeoServer发布PostgreSQL图层后WFS查询无主键字段
在使用 GeoServer(版本 2.22.2) 发布 PostgreSQL(PostGIS)中的表为地图服务时,常常会遇到一个小问题: WFS 查询中,主键字段(如 id)莫名其妙地消失了! 即使你在…...
深入解析 ReentrantLock:原理、公平锁与非公平锁的较量
ReentrantLock 是 Java 中 java.util.concurrent.locks 包下的一个重要类,用于实现线程同步,支持可重入性,并且可以选择公平锁或非公平锁的实现方式。下面将详细介绍 ReentrantLock 的实现原理以及公平锁和非公平锁的区别。 ReentrantLock 实现原理 基本架构 ReentrantLo…...