C++相关概念和易错语法(25)(列表初始化、initializer_list)

news2024/11/14 19:42:54

列表初始化是C++11中新增的初始化规则,大大增强了初始化的灵活性,在本篇文章中,我会详细讲解列表初始化的各种使用场景。

1.从C语言初始化语法开始改变——不带赋值号的初始化方式

列表初始化可以说是将C语言的一些初始化语法进行放大的结果。其中不带赋值号的初始化方式是一个很大的改变。

A a初始化就是在C语言中支持的,C++中同样支持。但在C++11中,这种结构体的初始化还能省略赋值=。这是从其它语言上借鉴过来的,在第一时间看到似乎觉得难以置信,但只要习惯了这种“不带赋值号的初始化方式”后,还是很好用的,后续的所有列表初始化都支持“不带赋值号的初始化方式”。

C语言的数组也是如此

注意好好理解不带赋值号的初始化,这对后续的学习很有帮助。

2.内置类型的初始化改变——支持{  }初始化规则

在C语言中内置类型的初始化都是形如int a = 0这样的,但C++11引入了一种新的初始化思想,即“不带赋值号初始化”,所以我们内置类型的初始化方式也有了新的适应方式,即{  }初始化

我们可以理解为,正是因为引入了“不带赋值号初始化”的思想,C++11的内置类型初始化规则才会做出改变。改变后的规则在逻辑上也是严密的。

在struct和数组中通常有多个数据,使用{1, 2, 3}这种方式来初始化。

对于内置类型,只有一个数据,那么我们依然可以用{1}来表达它。这又引入了{  }初始化的思想。从结构体和数组的初始化规则出发向外扩展,使得{  }初始化更加普遍化,统一化。

同时,“不带赋值号初始化”是一种选择,我们也可以像上面结构体和数组的初始化规则那样加上赋值号,这样的话struct、数组、内置类型在初始化上实现了大统一,都可以使用 = {  }或者单独的{  },从逻辑上来说这三者在这方面的初始化规则更紧密了。

枚举常量支持这种初始化

联合体也支持这种初始化

3.类对这种初始化规则的适应

很多人都在想struct难道不就是class吗?注意我上面分享的都是C++对C的兼容版本。struct里没有成员函数,只有成员变量。那么对于有成员函数的class,它的初始化规则是怎样的呢?

我们始终要记住“省略赋值号初始化”的和{  }统一初始化的两大目标,类的初始化规则也是根据这两大目标来拓展的。

(1)什么时候识别为C语言的struct?什么时候识别为class?

当有任何和C语言不相关的关键字出现时,都会被识别成class,包括访问限定符,以及class关键字

但要注意struct配上非构造函数的成员函数时,不会报错

这里的识别其实有点细了,稍微留意一下就好了。在绝大多数情况下,我们最好都不要写成C语言的结构体,都尽量写一个C++的类出来,尽量用class,如果用struct也最好写一个构造函数。

(2)类的{ }初始化调用构造函数

对于C++的类来说,依然延续了“省略赋值号初始化”的和{  }统一初始化两大原则

构造函数无参时

构造函数有参时

这里看上去很抽象,但仔细琢磨就会发现初始化的逻辑是合理的,和前面的结构体、内置类型、枚举等初始化规则一致。

4.类的数组的初始化——隐式类型转换的深入理解

这是将类和数组都结合在了一起,我们知道数组和类的统一初始化规则,类的数组同样遵循两大目标,依然保证语法逻辑严密。下面是一个实例,如果前面的理解透彻的话,这里就不会被绕晕

其实这就是套了两层初始化。我以第一个为例,{ { 1 } }应该怎样解读呢?

首先,A a[1]本质上是一个数组,我们就从数组入手,对于数组而言,初始化{  }里面放的是具体初始化的数据(如int a[2]{1, 2}),在这里{ { 1 } }最外层的{  }也是这个意思。

其次,这是一个自定义类型的数组,外层{  }里面放的应该是自定义类型A的具体元素,但是我们应该怎样表示出A的对象呢?这里就需要引入隐式类型转换的概念了。

对于数组而言,要初始化它,外层的{  }里面应该放的是具体的对象,如int a{1, 2, 3},但下面这种初始化同样可以

下面是一种易懂的理解

简单来说,根据列表的类型,编译器生成了相应个数的变量,这些变量用逗号之间的表达式初始化,最后再将这些变量存到内存中。因此,我们所说的隐式类型转换,其实可以理解为对自动生成的相应类型的变量进行初始化,最后将这些自动生成的变量存到内存中。如果说还有缺失的值,如int[10]只主动初始化4个,那么剩余的元素会用匿名对象的值填充。

我们可以用这样的思路解释刚刚的两种写法,而且应该会很轻松了。

对于所有自定义类型的列表都是这样,除了数组,类也是如此

但是一定要注意,只有自定义类型的列表才会自动生成这个变量,如int arr[],甚至int arr[1]也会,但是内置类型的就不会,列表里的内容不会进行任何转换,如int a,否则逻辑上会发生无穷递归的情况(和拷贝构造的引用类似,会无限生成变量)。

对于自定义类型来说一定会生成一个变量来接收列表中的内容用于变量初始化,也就是隐式类型转换。

深刻理解隐式类型转换是掌握C++11列表初始化的精髓,一定要用适合自己的方法理解这部分。

5.new中的列表初始化——沿用定义时初始化的思路,加深理解隐式类型转换的场景,指针转换

在内置类型中,初始化可用传统的(  )来进行,也可以用统一的{  }来进行。这也是“无赋值号初始化”思想引入初始化的一个巧合之处,本来new后的初始化就是紧跟着的,现在有一个统一的支持“无赋值号初始化”的{  }初始化方式,刚好可以完美替代原来的写法。

注意隐式类型转换依然只存在于new自定义类型,按我刚才分享的自动生成变量的思路来讲,内置类型是不会生成变量的,列表中必须是严格的匹配值(包括指针也算内置类型)

也不能发生任何指针类型的隐式类型转换

在这里顺便补充一下,C++中指针都必须手动强转,不仅是上面的那张图,所有场景都是如此,这是C++不同于C语言的一处细节

其余用法没有区别,注意的事项和上面提到的都一样

注意缺失值都是按匿名对象的值填充,int()一定是0,在所有编译器上都是,而不是靠编译器选择

6.用变量初始化

用变量初始化也同样遵循上面的原则,只不过需要注意对于内置类型,不会进行任何的隐式类型转换(没有变量生成),就算是整型提升或截断也不行

在要生成变量的数组或类中才能不主动强转(中间生成的变量会隐式类型转换一次),但也会有警告,所以最好避免这些情况

7.initializer_list
initializer_list本质上也是“不带赋值符号初始化”和“{  }统一初始化”的产物,其实我上面讲到的所有单参数列表中{  }都可以叫做初始化列表,如int a{ 1 }就算。多参数列表里面的{ }按照自动生成变量的理解方式来看也可以叫做初始化列表,这一点其实很灵活,因为初始化列表本身就是一个很灵活的容器,只要是{  }格式的都可以算作初始化列表

initializer_list可以接收任意数量的元素,即{  }里面可以随便放,这也是为了兼容数组初始化时int a[] = {  }里面可以放任意个数据。接收到的initializer_list会从最小元素开始去自动匹配对应的构造函数(如类的数组{ {1}, {1, 2} }会先把{1}, {1, 2}拿去调用类的构造,生成对象),内置类型也会调用对应的构造(匿名构造的统一,如int(1)),最后如果最外层{  }有数组就分别存储它们的值。

在C++11后,所有容器都支持用initializer_list来初始化

因为如果不显式支持initializer_list初始化的话,当使用{  }这种统一方式来调用构造函数的话,传的参数个数不同可能会导致匹配到不同的构造函数,如果专门有个initializer_list的构造函数的话,就不会乱匹配,导致功能错误

有initializer_list构造函数

无initializer_list构造函数

如果只保留一个,那当然也能匹配

仔细理解initializer_list,它本质上就是一种为了适应新语法而诞生的一种容器,它的出现使得之前数组的初始化语法(int arr[] = { })更有逻辑性,它匹配构造函数的原则也解释了上面列表初始化的更深的原理。

列表初始化涉及的点特别地多,单看某一部分的语法可能还行,但要串联起这个逻辑却是很难的,因为它是一种旧语法的延伸,将原本简单的数组初始化语法扩展为庞大的统一化的初始化体系,还引入了其它语法的思想。这需要我们慢慢理解背后的逻辑,消化好之后会发现列表初始化其实挺好用的。

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

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

相关文章

c++习题18-计算鞍点

目录 一,题目 二,思路 三,代码 一,题目 给定一个55的矩阵,每行只有一个最大值,每列只有一个最小值,寻找这个矩阵的鞍点。鞍点指的是矩阵中的一个元素,它是所在行的最大值&#x…

海外短剧小程序 ,竖屏会员付费看剧系统搭建paypal,stripe对接支付功能

目录 前言: 一、系统功能 二、系统常见问题 总结: 前言: 在全球化的今天,短剧作为一种新兴的内容形式,正迅速赢得国际观众的心。尤其是海外市场的短剧推广,正成为内容创作者和营销者的新宠。本文将深入…

AWS云服务器选择最佳区域

2024年,随着全球云计算的持续发展和AWS在全球不断扩展的数据中心网络,选择合适的AWS云服务器区域成为了企业和开发者需要认真考虑的问题。九河云告诉你在做出选择之前,需要考虑以哪些关键因素: 地理位置和用户分布 选择AWS云服务…

06:【stm32】OLED模块的简单使用

OLED模块的简单使用 OLED简单的使用 OLED简单的使用 OLED驱动函数是使用B站UP江科大的。我们直接调用即可,是使用软件模拟I2C协议进行通信的。具体的I2C协议可查看上官嵌入式开发中的C51单片机开发。 驱动函数文件:通过百度网盘分享的文件:…

ShardingSphere之ShardingProxy集群部署

文章目录 介绍使用Zookeeper进行集群部署统一ShardingJDBC和ShardingProxy配置通过Zookeeper注册中心同步配置直接使用ShardingProxy提供的JDBC驱动读取配置文件 介绍 开发者手册 在conf/server.yaml配置文件中有下面这一段配置,就是关于集群部署的 mode: # typ…

JAVA 封装一个工具类,将实例的里面的空值设为对应的默认值

JAVA 封装一个工具类&#xff0c;将实例的里面的空值设为对应的默认值&#xff0c;比喻字符串类型就设为默认 "", Integer就设为0 示例代码&#xff1a; protected static void setDefaults(Object obj) {Class<?> clazz obj.getClass();Field[] fields …

如何在FreeRtos工程中添加驱动调用

前言&#xff1a;本篇笔记学习的是韦东山老师的教程&#xff0c;连接放在最后。 上篇教程图文讲解了&#xff0c;如何使用STM32CubleMX&#xff0c;进行移植FreeRtos工程&#xff0c;如果没有使用这个软件则需要自己去手动进行移植操作&#xff0c;本篇图文教程是添加驱动&…

LeetCode.3132.找出与数组相加的整数II

题目描述&#xff1a; 给你两个整数数组 nums1 和 nums2。 从 nums1 中移除两个元素&#xff0c;并且所有其他元素都与变量 x 所表示的整数相加。如果 x 为负数&#xff0c;则表现为元素值的减少。 执行上述操作后&#xff0c;nums1 和 nums2 相等 。当两个数组中包含相同…

【探索数据结构与算法】使用单链表实现队列

目录 一. 队列的定义 二.队列的结构定义 单个元素的结构定义 队列的结构定义 三.队列的接口实现 1.初始化 2.销毁 3.入队列&#xff08;队尾插入&#xff09; 4.出队列&#xff08;队头删除&#xff09; 5.获取队首元素 6.获取队尾元素 7.获取队列元素个数 …

力扣刷题-环形链表II

&#x1f308;个人主页&#xff1a;羽晨同学 &#x1f4ab;个人格言:“成为自己未来的主人~” 我们先来看一下这道题的代码部分&#xff1a; /*** Definition for singly-linked list.* struct ListNode {* int val;* struct ListNode *next;* };*/ struct ListN…

element table表格树形数据展示

element table表格树形数据展示 1、效果 2、代码 <el-table ref"pointMultipleTable" border class"table-box" :data"[damActiveObj]"row-key"id" :tree-props"{ children: children }" :expand-row-keys"expand…

Qt+TSC打印机调试

前言 最近被TSC打印机整的死去活来&#xff0c;记录一下使用方法。 一、环境 Qt5.15.2 mingw tsc TE244 二、使用步骤 1.引入库 从官网下载windows C SDK&#xff0c;引入库&#xff0c;以下是.pro文件 QT core gui printsupportgreaterThan(QT_MAJOR_VERSION, 4)…

HAProxy七层负载均衡配置方案

HAProxy 一、准备二、配置HAProxy服务器1. 下载HAProxy2. 编写配置文件3. 启动HAProxy服务 三、配置后端服务①配置web服务器②配置php服务器 四、测试 一、准备 准备5台CentOS7服务器&#xff0c;IP地址如下&#xff1a; HAProxy 192.168.152.71web1 192.168.152.72web2 192.…

3D摄影棚布光软件:Set A Light 3D Studio for Mac 激活版

Set A Light 3D Studio 是一款专业的照明模拟软件&#xff0c;专为摄影师和电影制作人设计&#xff0c;用于规划和设计照片拍摄的照明效果。 以下是关于这款软件的一些主要特点和功能&#xff1a; 虚拟照明工作室&#xff1a;Set A Light 3D Studio 提供了一个虚拟的照明工作室…

CentOS7.6 HAproxy-7层负载均衡集群——实施方案

目录 1、前期环境准备 1.准备4台主机 1. 设置主机名 2. 设置IP地址然后重启网卡 3. 关闭防火墙和selinux 4. 全部的服务器完成时间统一 二、配置haproxy(192.168.200.11)服务器 1. 安装haproxy 2. haproxy 配置中分成五部分内容 3. 配置HAproxy&#xff08;192.168.2…

大家不推荐开放式耳机?开放式耳机的优缺点

你问到了一个挺有意思的问题&#xff1a;为什么大家在推荐耳机时&#xff0c;往往不太提那些在抖音上卖得火热的开放式耳机呢&#xff1f; 首先&#xff0c;咱得明白&#xff0c;抖音上的热门产品&#xff0c;很多时候是因为它们抓住了短视频的“爆款”特性——要么是颜值爆表&…

代码随想录算法训练营第十八天| 530.二叉搜索树的最小绝对差 ● 501.二叉搜索树中的众数 ● 236. 二叉树的最近公共祖先

题目&#xff1a; 530. 二叉搜索树的最小绝对差 给你一个二叉搜索树的根节点 root &#xff0c;返回 树中任意两不同节点值之间的最小差值 。 差值是一个正数&#xff0c;其数值等于两值之差的绝对值。 示例 1&#xff1a; 输入&#xff1a;root [4,2,6,1,3] 输出&#xff1a;…

共谱绿色物流新篇章!批量苏州金龙氢燃料牵引车交付张家港

2024年8月8日上午阳光明媚&#xff0c;一场别开生面的交车仪式在苏州金龙厂区内举行。张家港运昌绿色物流有限公司&#xff08;以下简称“张家港运昌物流”&#xff09;采购的40台苏州金龙氢燃料牵引车正式交付。江苏华昌&#xff08;集团&#xff09;有限公司纪委书记陈饶忠&a…

Robot Operating System——深度解析通过符号和隐式加载动态库的运行模式

大纲 运行时分析依赖文件分析汇编和符号分析 除了《Robot Operating System——深度解析自动隐式加载动态库的运行模式》中介绍的这种最终在底层依赖了RCLCPP_COMPONENTS_REGISTER_NODE来注册Node工厂类对象之外&#xff0c;还存在一种特殊的方式&#xff0c;即本文介绍的&…

仿RabbiteMq简易消息队列基础篇(gtest的使用)

TOC gtest介绍 gtest是google的一个开源框架&#xff0c;它主要用于写单元测试&#xff0c;检查自己的程序是否符合预期行为。可在多个平台上使用&#xff08;包含Linux&#xff0c;MAC OC&#xff0c;Windows等&#xff09;。它提供了丰富的断言&#xff0c;致命和非致命失败…