【C++】深入剖析C++11 initializer_list 新的类功能 可变模板参数

目录

一、std::initializer_list

1、std::initializer_list是什么类型 

2、std::initializer_list 的应用场景

①给自定义容器赋值

② 传递同类型的数据集合

二、新的类功能

1、默认成员函数

2、关键字default

3、关键字delete

三、可变参数模板


一、std::initializer_list

  • initializer_list是一种标准库类型,用于表示某种特定类型的值的数组。和vector一样,initializer_list也是一种模板类型,定义 initializer_list 对象时,必须说明列表中所含元素的类型。和vector不一样的是,initializer_list 对象中的元素永远是常量值,我们无法改变 initializer_list 对象中元素的值。
  •  initializer_list 可以作用于可变数量的实参,有时我们无法提前预知应该向函数传递几个实参。为了编写能处理不同数量实参的函数,C++11新标准提供了两种主要的方法:①如果所有的实参类型相同,可以传递一个名为 initializer_list 的标准库类型;②如果实参的类型不同,我们可以编写一种特殊的函数,也就是所谓的可变参数模板。
  •  作用于 initializer_list 对象的begin和end操作类似于vector对应的成员。begin()成员提供一个指向列表首元素的指针,end()成员提供一个指向列表尾元素的指针。
  •  含有 initializer_list 形参的函数也可以同时拥有其他形参。
  •  类模板 initializer_list 用于访问初始化列表(initialization list),列表元素的数据类型为const T.编译器从花括号(brace)封闭的、元素由逗号分隔开的初始化列表自动构造initializer_list模板类,例如:
  • auto il = {10,20, 30}; // the type of il is an initializer_list<int>
  • 【initializer_list 官方文档】

1、std::initializer_list是什么类型 

 2、std::initializer_list 的应用场景

这里 arr 没有显式指定长度,因此,它的初始化列表可以是任意长度。

同样, std::map、 std::set、 std::vector 也可以在初始化时任意书写需要初始化的内容。

自定义的 Foo 却不具备这种能力,只能按部就班地按照构造函数指定的参数列表进行赋值。

实际上, stl 中的容器是通过使用 std::initializer_list 这个轻量级的类模板来完成上述功能支持的。我们只需要为 Foo 添加一个 std::initializer_list 构造函数,它也将拥有这种任意长度初始化的能力

①给自定义容器赋值

这里定义了两个自定义容器,一个是 FooVector,采用 std::vector<int> 作为内部存储;另一个是 FooMap,采用 std::map<int, int> 作为内部存储。

可以看到, FooVector、 FooMap 的初始化过程,就和它们使用的内部存储结构一样。

这两个自定义容器的构造函数中, std::initializer_list 负责接收初始化列表。并通过我们熟知的 for 循环过程,把列表中的每个元素取出来,并放入内部的存储空间中。

② 传递同类型的数据集合

如上述所示,在任何需要的时候, std::initializer_list 都可以当作参数来一次性传递同类型的多个数据。 

二、新的类功能

1、默认成员函数

原来C++类中,有6个默认成员函数:

  •  构造函数
  • 析构函数
  • 拷贝构造函数
  • 拷贝赋值重载
  • 取地址重载
  • const 取地址重载

最后重要的是前4个,后两个用处不大。默认成员函数就是我们不写编译器会生成一个默认的。 C++11 新增了两个:移动构造函数移动赋值运算符重载

针对移动构造函数和移动赋值运算符重载有一些需要注意的点如下:

  • 如果你没有自己实现移动构造函数,且没有实现析构函数 、拷贝构造、拷贝赋值重载中的任意一个。那么编译器会自动生成一个默认移动构造。默认生成的移动构造函数,对于内置类型成员会执行逐成员按字节拷贝,自定义类型成员,则需要看这个成员是否实现移动构造, 如果实现了就调用移动构造,没有实现就调用拷贝构造。
  • 如果你没有自己实现移动赋值重载函数,且没有实现析构函数 、拷贝构造、拷贝赋值重载中的任意一个,那么编译器会自动生成一个默认移动赋值。默认生成的移动构造函数,对于内置类型成员会执行逐成员按字节拷贝,自定义类型成员,则需要看这个成员是否实现移动赋值,如果实现了就调用移动赋值,没有实现就调用拷贝赋值。(默认移动赋值跟上面移动构造完全类似) 如果你提供了移动构造或者移动赋值,编译器不会自动提供拷贝构造和拷贝赋值。

 2、关键字default

C++11可以让你更好的控制要使用的默认函数。假设你要使用某个默认的函数,但是因为一些原 因这个函数没有默认生成。比如:我们提供了拷贝构造,就不会生成移动构造了,那么我们可以 使用default关键字显示指定移动构造生成。

3、关键字delete

如果能想要限制某些默认函数的生成,在C++98中,是该函数设置成private,这样只要其他人想要调用就会报错。在C++11中更简单,只需在该函数声明加上=delete即 可,该语法指示编译器不生成对应函数的默认版本,称=delete修饰的函数为删除函数。 

三、可变参数模板

C++11的新特性可变参数模板能够让您创建可以接受可变参数的函数模板和类模板,相比 C++98/03,类模版和函数模版中只能含固定数量的模版参数,可变模版参数无疑是一个巨大的改 进。然而由于可变模版参数比较抽象,使用起来需要一定的技巧,所以这块还是比较晦涩的。现 阶段呢,我们掌握一些基础的可变参数模板特性就够我们用了,所以这里我们点到为止,以后大 家如果有需要,再可以深入学习。

上面的参数args前面有省略号,所以它就是一个可变模版参数,我们把带省略号的参数称为“参数 包”,它里面包含了0到N(N>=0)个模版参数。我们无法直接获取参数包args中的每个参数的, 只能通过展开参数包的方式来获取参数包中的每个参数,这是使用可变模版参数的一个主要特 点,也是最大的难点,即如何展开可变模版参数。由于语法不支持使用args[i]这样方式获取可变 参数,所以我们的用一些奇招来一一获取参数包的值。

 

在不定参数的模板函数中,还可以通过如下方式获得args的参数个数:

【逗号表达式展开参数包】

  • 这种展开参数包的方式,不需要通过递归终止函数,是直接在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数组的过程中就将参数包展开了,这个数组的目的纯粹是为了在 数组构造的过程展开参数包.

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

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

相关文章

信创基础软件之中间件

信创基础软件之中间件 中间件概述 中间件是一种应用于分布式系统的基础软件&#xff0c;位于应用与操作系统、数据库之间&#xff0c;主要用于解决分布式环境下数据传输、数据访问、应用调度、系统构建和系统集成、流程管理等问题&#xff0c;是分布式环境下支撑应用开发、运…

读取打包到JAR中的文件:常见问题与解决方案(文件在但是报错not find)

读取打包到JAR中的文件&#xff1a;常见问题与解决方案 喝淡酒的时候&#xff0c;宜读李清照&#xff1b;喝甜酒时&#xff0c;宜读柳永&#xff1b;喝烈酒则大歌东坡词。其他如辛弃疾&#xff0c;应饮高梁小口&#xff1b;读放翁&#xff0c;应大口喝大曲&#xff1b;读李后主…

android init进程启动流程

一,Android系统完整的启动流程 二,android 系统架构图 三,init进程的启动流程 四,init进程启动服务的顺序 五,android系统启动架构图 六,Android系统运行时架构图 bool Service::Start() {// Starting a service removes it from the disabled or reset state and// imme…

【redis】redis持久化分析

目录 持久化Redis持久化redis持久化的方式持久化策略的设置1. RDB&#xff08;快照&#xff09;fork(多进程)RDB配置触发RDB备份自动备份手动执行命令备份&#xff08;save | bgsave&#xff09;flushall命令主从同步触发动态停止RDB RDB 文件恢复验证 RDB 文件是否被加载 RDB …

c++:(map和set的底层简单版本,红黑树和AVL树的基础) 二叉搜索树(BST)底层和模拟实现

文章目录 二叉搜索树的概念二叉搜索树的操作二叉搜索树的查找find 二叉搜索树的模拟实现构造节点insertfinderase(细节巨多,面试可能会考)a.叶子节点b.有一个孩子左孩子右孩子 c.有两个孩子注意: erase代码 中序遍历 二叉搜索树的应用k模型k模型模拟实现的总代码 k-value模型k-…

代码随想录算法训练营第六十天| LeetCode647. 回文子串 、516.最长回文子序列

一、LeetCode647. 回文子串 题目链接/文章讲解/视频讲解&#xff1a;https://programmercarl.com/0647.%E5%9B%9E%E6%96%87%E5%AD%90%E4%B8%B2.html 状态&#xff1a;已解决 1.思路 这道题我只想出来了暴力解法&#xff0c;动规解法并没有想出来。根据视频讲解才把它想出来。…

聚观早报 | 苹果新款iPad Pro发布;国产特斯拉4月交付量

聚观早报每日整理最值得关注的行业重点事件&#xff0c;帮助大家及时了解最新行业动态&#xff0c;每日读报&#xff0c;就读聚观365资讯简报。 整理丨Cutie 5月9日消息 苹果新款iPad Pro发布 国产特斯拉4月交付量 iOS 18新功能爆料 真我GT Neo6续航细节 三星Galaxy Z F…

智慧公厕,小民生里的“大智慧”!

公共厕所是城市社会生活的基础设施&#xff0c;而智慧公厕则以其独特的管理模式为城市居民提供更优质的服务。通过智能化的监测和控制系统&#xff0c;智慧公厕实现了厕位智能引导、环境监测、资源消耗监测、安全防范管理、卫生消杀设备、多媒体信息交互、自动化控制、自动化清…

uniapp——弹出键盘遮挡住输入框 textarea,处理方法

案例 在写输入框的时候会遇见 键盘遮挡住部分textarea框的一部分&#xff0c;使用cursor-spacing处理即可 修改后&#xff1a; 其他问题&#xff1a; 调起键盘输入时&#xff0c;不希望上方的内容被顶上去 代码 <view class"commentBox" :style"botto…

什么是HTTP?

什么是HTTP&#xff1f; HTTP基本概念HTTP 是什么&#xff1f;HTTP 常见的状态码有哪些&#xff1f;HTTP 常见字段有哪些&#xff1f; HTTP特性HTTP/1.1 的优点有哪些&#xff1f;HTTP/1.1 的缺点有哪些&#xff1f; HTTP基本概念 HTTP 是什么&#xff1f; HTTP 是超文本传输…

基于Springboot的果蔬作物疾病防治系统(有报告)。Javaee项目,springboot项目。

演示视频&#xff1a; 基于Springboot的果蔬作物疾病防治系统&#xff08;有报告&#xff09;。Javaee项目&#xff0c;springboot项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系…

4.【Orangepi Zero2】Linux定时器(signal、setitimer),软件PWM驱动舵机(SG90)

Linux定时器&#xff08;signal、setitimer&#xff09;&#xff0c;软件PWM驱动舵机&#xff08;SG90&#xff09; signalsetitimer示例 软件PWM驱动舵机&#xff08;SG90&#xff09; signal 详情请看Linux 3.进程间通信&#xff08;shmget shmat shmdt shmctl 共享内存、si…

内容安全(DPI和DFI解析)

内容安全前言&#xff1a; 防火墙的本质其实就是包过滤&#xff0c;我们通常所说的安全设备&#xff08;如&#xff1a;IPS、IDS、AV、WAF&#xff09;的检测重心是应用层。下一代防火墙基于传统防火墙的拓展能力&#xff0c;就是可以将以上的安全设备模块集成在一起&#xff0…

HackMyVM-Animetronic

目录 信息收集 arp nmap nikto whatweb WEB web信息收集 feroxbuster steghide exiftool hydra ssh连接 提权 系统信息收集 socat提权 信息收集 arp ┌──(root㉿0x00)-[~/HackMyVM] └─# arp-scan -l Interface: eth0, type: EN10MB, MAC: 08:00:27:9d:6d:7…

anaconda虚拟环境pytorch安装

1.先创建conda的虚拟环境 conda create -n gputorch python3.102.激活刚刚创建好的虚拟环境 conda activate gputorch3.设置国内镜像源 修改anaconda的源&#xff0c;即修改.condarc配置文件 .condarc在 home/用户/user/ conda config --add channels https://mirrors.tuna.…

题目----力扣--移除链表元素

题目 给你一个链表的头节点 head 和一个整数 val &#xff0c;请你删除链表中所有满足 Node.val val 的节点&#xff0c;并返回 新的头节点 。 示例 1&#xff1a; 输入&#xff1a;head [1,2,6,3,4,5,6], val 6 输出&#xff1a;[1,2,3,4,5]示例 2&#xff1a; 输入&…

【Python爬虫实战入门】:教你一个程序实现PPT模版自由

文章目录 &#x1f4a5;一、PPT模版爬取&#x1f525;1.1 第一个爬虫&#x1f6b2;1. 获取下载页面链接 ❤️1.2 第二个爬虫&#x1f6b2;1.3 第三个爬虫&#x1f388;2. 文件保存 ❤️1.4 翻页处理 &#x1f525;二、完整代码 &#x1f525;&#x1f525;&#x1f525; Pytho…

安卓手机原生运行 ARM Ubuntu 24.04 桌面版(一)

本篇文章&#xff0c;聊一聊尝试让安卓手机原生运行 Ubuntu&#xff0c;尤其是运行官方未发布过的 ARM 架构的 Ubuntu 24.04 桌面版本。 写在前面 最近的几篇文章&#xff0c;都包含了比较多的实操内容、需要反复的复现验证&#xff0c;以及大量的调试过程&#xff0c;为了不…

【C++语言】Date类的代码实现(操作符重载运用)

文章目录 前言Date类的构思Date类的相关实现基本框架&#xff08;默认成员函数&#xff09;计算n天前\后的日期补充&#xff1a;前置、后置说明判断两个日期的关系&#xff08;大于&#xff0c;小于等&#xff09;&#xff1b;可以计算两个日期之间相差多少天补充&#xff1a;流…

SQLI-labs-第十三关和第十四关

目录 第十三关 1、判断注入点 2、判断当前数据库 3、爆表名 4、爆字段名 5、爆值 第十四关 1、判断注入点 知识点&#xff1a;POST方式的单引号和括号闭合错误,报错注入 第十三关 思路&#xff1a; 1、判断注入点 使用Burpsuite抓包 首先加入一个单引号&#xff0c;…