【C++】再识构造函数:初始化列表新方式

欢迎来到CILMY23的博客

🏆本篇主题为: 再识构造函数:初始化列表新方式

🏆个人主页:CILMY23-CSDN博客

🏆系列专栏:Python | C++ | C语言 | 数据结构与算法 | 贪心算法 | Linux

🏆感谢观看,支持的可以给个一键三连,点赞关注+收藏。


写在前头:

在之前我们花了大篇幅了解了构造函数,包括但不限于构造函数的详解,构造函数和析构函数的顺序,以及构造函数中特殊的拷贝构造函数。那这次的构造函数又会带给我什么惊喜呢?


目录

再见构造函数

1️⃣ 构造函数赋值

2️⃣ 初始化列表的概念

3️⃣ 为什么会有初始化列表? 

4️⃣ 初始化列表的特点 

5️⃣ 构造函数新的写法

6️⃣ explicit关键字 

7️⃣ 多参数类型的隐式转换 


再见构造函数

1.1  构造函数赋值

在创建对象时,编译器通过调用构造函数,给对象中各个成员变量一个合适的初始值。

class Student
{
public://无参构造函数Student(){strcpy(_name, "xxxxxx");_age = 0;strcpy(_ID, "xxxxxxx");}void Print(){cout << "学生姓名:" << _name << endl;cout << "学生年龄:" << _age << endl;cout << "学生学号:" << _ID << endl;}
private:char _name[20];int _age;char _ID[20];
};int main()
{Student stu1;//调用了无参的构造函数stu1.Print();return 0;
}

虽然上述构造函数调用之后,对象中已经有了一个初始值,但是不能将其称为对对象中成员变量 的初始化,构造函数体中的语句只能将其称为赋初值,而不能称作初始化。因为初始化只能初始 化一次,而构造函数体内可以多次赋值

1.2  初始化列表的概念

初始化列表是C++中的一个功能,允许在构造函数中直接初始化成员变量,而非在构造函数体内赋值。初始化列表直接跟在构造函数的参数列表后面,以冒号开始后面紧跟一个或多个用逗号分隔的初始化表达式。这些表达式直接对成员变量或自定义类型进行初始化。

例如:这里有个学生类,我们要用初始化列表。(在这里对字符的拷贝我们仍然采用C的方法来实现,利用strncpy或者strcpy,在之后我们会用string来实现这些)

class Student {
public:// 使用初始化列表来初始化_ageStudent(const char* name, int age, const char* ID) : _age(age) {// 为_name和_ID赋值strncpy(_name, name, sizeof(_name) - 1);_name[sizeof(_name) - 1] = '\0'; strncpy(_ID, ID, sizeof(_ID) - 1);_ID[sizeof(_ID) - 1] = '\0'; }private:char _name[20];int _age;char _ID[20];
};int main()
{Student student1("Alice", 20, "1234567890");student1.Print();return 0;
}

1.3 为什么会有初始化列表? 

 例如:就像下面这段代码一样,有些类的成员是必须要在初始化的时候定义的,这里的_n = -1;是会报错的。就比如const成员是这样的。那哪个地方是初始化的呢?那它就需要去构造函数去找空间给它初始化,但也会有安全性的问题,所以有了初始化列表这个概念。初始化列表是每个成员变量定义初始化的位置。

顺序是先走上面的初始化列表,然后再走函数体内的赋值修改,能用初始化列表就用初始化列表。

class Student 
{
public://Student(const char* name, int age, const char* ID) //    : _age(age) //{//    //赋值修改//    strncpy(_name, name, sizeof(_name) - 1);//    _name[sizeof(_name) - 1] = '\0'; //}//构造函数Student(const char* name, int age){strncpy(_name, name, sizeof(_name) - 1);_name[sizeof(_name) - 1] = '\0';_age = age;_n = -1; // 无法修改}private://声明char _name[20];int _age = 1; //缺省值const int _n;
};int main() 
{//对象实例化Student student1("Alice", 20);return 0;
}

1.4 初始化列表的特点 

  1. 每个成员变量在初始化列表中只能出现一次(初始化只能初始化一次)
  2. 类中包含以下成员,必须放在初始化列表位置进行初始化,这三个在函数体内不能初始化

    ✔️引用成员变量
    ✔️const成员变量
    ✔️自定义类型成员(且该类没有默认构造函数时)

  3. 尽量使用初始化列表初始化,因为不管你是否使用初始化列表,对于自定义类型成员变量, 一定会先使用初始化列表初始化。
  4. 成员变量在类中声明次序就是其在初始化列表中的初始化顺序,与其在初始化列表中的先后 次序无关 

这些特点如下所示: 

class A
{
public:A(int x)//初始化列表:_a(1){//赋值修改_a = x;}private:int _a;
};class Student
{
public://初始化列表是每个成员变量定义初始化的位置//能用初始化列表就用初始化列表Student(const char* name, int age, int &x): _age(age), _n(1), _aa(1)//显式调用构造函数, ref(x){strncpy(_name, name, sizeof(_name) - 1);_name[sizeof(_name) - 1] = '\0'; }private://声明char _name[20];int _age = 1; //缺省值//必须走初始化列表//1. const 成员 //2. 引用成员变量//3. 自定义类型成员const int _n;int& ref;A _aa;
};int main()
{//对象实例化int x = 0;Student student1("Alice", 20,x);return 0;
}

 1.5 构造函数新的写法

构造函数结合初始化列表后,我们可以写成main函数中的另外两种cc的形式。 

class C
{
public:C(int x = 0):_x(x){}
private:int _x;
};class B
{
public:B():_p(2),_p1((int*)malloc(sizeof(4)*10)){if (_p1 == nullptr){perror("malloc fail");}}
private://缺省值是给初始化列表的int _p = 1;int* _p1 = (int*)malloc(sizeof(4));
};int main()
{B bb;//构造函数的写法C cc1(1);//2构造一个临时对象,再拷贝构造C cc2 = 2;return 0;
}

 其实通过这个例子我们可以发现,单参数构造函数支持隐式类型的转换,2构造一个临时对象,然后再拷贝构造

如果遇到同一个表达式连续步骤的构造,一般会被编译器优化。 

隐式类型转换是有好处的,例如我们在栈传参的时候,可以直接将int类型的4转换成自定义类型。

1.6 explicit关键字 

如果你不想让上述这种隐式类型转换发生,那你就可以加一个关键字 - explicit。 

  

1.7 多参数类型的隐式转换 

在目前的C++11中,支持多参数类型的隐式转换,C++98还不支持,用花括号括起来。


总结:

  • 初始化列表直接跟在构造函数的参数列表后面,以冒号开始后面紧跟一个或多个用逗号分隔的初始化表达式
  • 顺序是先走上面的初始化列表,然后再走函数体内的赋值修改
  • 当出现函数赋值修改缺省值,和初始化列表的时候,推荐是能用初始化列表就用初始化列表。
  • 有些成员必须走初始化列表,1. const 成员 2. 引用成员变量 3. 自定义类型成员(没有默认构造的自定义类型成员)
  • 成员变量在类中声明次序就是其在初始化列表中的初始化顺序,与其在初始化列表中的先后 次序无关
  • 缺省值是给初始化列表的
  • 单参数构造函数支持隐式类型的转换
  • 临时变量具有常性,需要加const修饰。
  • 构造函数不仅可以构造与初始化对象,对于单个参数或者除第一个参数无默认值其余均有默认值的构造函数,还具有类型转换的作用。
  • explicit 可以限制隐式类型的转换
  • C++11 支持多参数类型的隐式类型转换

感谢各位同伴的支持,本期C++就讲解到这啦,如果你觉得写的不错的话,可以给个一键三连,点赞,关注+收藏,若有不足,欢迎各位在评论区讨论。  

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

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

相关文章

一种快速H.264 NALU快速搜索算法

1. 引言 在播放H.264码流的时候,进行NALU的搜索的效率高低影响着系统的性能。有采用普通逐字节搜索的算法,有利用cpu的simd的单指令多数据操作的并行功能进行搜索的算法,今天要介绍的是一个非常简单而且高效的快速搜索算法,而且不需要利用simd指令,搜索的速度甚至快于我之…

Vue的学习 —— <初识vue>

目录 前言 目标 前端的发展历程 正篇开始——Vue讲解 一、Vue简介 二、Vue特性 1、数据驱动视图 2、双向数据绑定 3、指令 4、插件 三、vue的三大版本 前言 在这个快速迭代的互联网时代&#xff0c;前端技术的发展日新月异&#xff0c;Vue.js的出现无疑为前端开发领…

深度解析Nginx:高性能Web服务器的奥秘(下)

&#x1f407;明明跟你说过&#xff1a;个人主页 &#x1f3c5;个人专栏&#xff1a;《洞察之眼&#xff1a;ELK监控与可视化》&#x1f3c5; &#x1f516;行路有良友&#xff0c;便是天堂&#x1f516; 目录 一、前言 1、Nginx概述 二、Nginx核心功能 1、URL重写与重…

git-将本地项目上传到远程仓库

在gitee中新建一个远程仓库。 填写对应内容。 打开你想上传的文件夹&#xff0c;比如我想上传yuanshen 右击&#xff0c;打开git bash 输入git init初始化仓库 git init 添加项目所有文件 git add . 将添加的文件提交到本地仓库&#xff08;提交说明必填&#xff09; git …

Python 全栈系列246 任务调度对象WFlaskAPS

说明 之前已经完全跑通了任务调度&#xff0c;实现了S2S的流转Python 全栈系列243 S2S flask_celery。由于request请求用起来比较别扭&#xff0c;所以创建一个对象来进行便捷操作。 内容 1 功能 WFlaskAPS包含管理定时任务的必要功能 from datetime import datetime from…

嵌入式CAN通信协议详解分析

CAN协议简介 CAN是控制器局域网络(Controller Area Network)的简称,它是由研发和生产汽车电子产品著称的德国BOSCH公司开发的,并最终成为国际标准(ISO11519),是国际上应用最广泛的现场总线之一。 CAN总线协议已经成为汽车计算机控制系统和嵌入式工业控制局域网的标准总线…

算法课程笔记——自下而上树形DP

算法课程笔记——自下而上树形DP #include<bits/stdc.h>usingnamespacestd; constintN100005; intn,a[N]; longlongdp[N][2]; vector<int> e[N]; voiddfs(intu){for(autov:e[u]){dfs(v);dp[u][1]dp[v][0];dp[u][0]max(dp[v][0],dp[v][1]);}dp[u][1]a[u]; } intmain…

图像分类——猫狗图片

引言 亲爱的读者们&#xff0c;您是否在寻找某个特定的数据集&#xff0c;用于研究或项目实践&#xff1f;欢迎您在评论区留言&#xff0c;或者通过公众号私信告诉我&#xff0c;您想要的数据集的类型主题。小编会竭尽全力为您寻找&#xff0c;并在找到后第一时间与您分享。 …

如何用Rust获取CPU、内存、硬盘的信息?

目录 一、用Rust获取CPU、内存、硬盘的信息 二、知识点 systemstat 一、用Rust获取CPU、内存、硬盘的信息 首先&#xff0c;需要添加systemstat库到Cargo.toml文件&#xff1a; [dependencies] systemstat "0.8.2" 在Rust代码中使用它&#xff1a; extern crat…

新增柱线组合图、象限图,新增钉钉、飞书、企业微信客户端免密登录,DataEase开源数据可视化分析工具v2.6.0发布

2024年5月13日&#xff0c;人人可用的开源数据可视化分析工具DataEase正式发布v2.6.0版本。 这一版本的功能升级包括&#xff1a;图表方面&#xff0c;新增了柱线组合图、象限图&#xff1b;仪表板方面&#xff0c;支持批量拖拽字段&#xff0c;外部参数新增支持配置过滤组件&…

日元崩了:日本上市公司转战比特币作对冲

5月13日&#xff0c;日本上市公司Metaplanet发布公告宣布因为政府债务水平高企、实际利率长期处于负值以及日元贬值&#xff0c;Metaplanet特将比特币作为其公司战略储备资产&#xff0c;以回应日本严峻的经济形势。同时也为当地资产管理领域的企业创新开创了先例。 Metaplanet…

AtCoder Beginner Contest 308 B题 Default Price

B题&#xff1a;Default Price 标签&#xff1a; S T L 、 m a p STL、map STL、map、模拟 题意&#xff1a;给定 n n n个有颜色的盘子和 m m m种颜色分别对应的价值 p i p_i pi​&#xff0c; p 0 p_0 p0​表示盘子颜色如果不属于这 m m m种颜色&#xff0c;那对应的价值&…

Flutter 中的 Visibility 小部件:全面指南

Flutter 中的 Visibility 小部件&#xff1a;全面指南 在 Flutter 中&#xff0c;Visibility 是一个用于根据布尔值条件显示或隐藏小部件的控件。使用 Visibility 可以避免不必要的布局占用&#xff0c;因为它实际上会从布局树中移除符合条件的小部件。 基础用法 Visibility…

Spring AOP切面实现为mapper层指定方法入参字段赋值

需求&#xff1a; 有时候我们在进行某些操作时&#xff0c;可能需要额外进行复制操作&#xff0c;而这些字段往往不是由前端/客户端填写输入的&#xff0c;而是由后端给与&#xff0c;类似于 登陆者、创建时间、更新时间等字段&#xff0c;这时&#xff0c;可以借助AOP指定mapp…

强化学习——马尔可夫奖励过程的理解

目录 一、马尔可夫奖励过程1.回报2.价值函数 参考文献 一、马尔可夫奖励过程 在马尔可夫过程的基础上加入奖励函数 r r r 和折扣因子 γ \gamma γ&#xff0c;就可以得到马尔可夫奖励过程&#xff08;Markov reward process&#xff09;。一个马尔可夫奖励过程由 < S , …

Vue从入门到实战Day05

一、自定义指令 自定义指令&#xff1a;自己定义的指令&#xff0c;可以封装一些dom操作&#xff0c;扩展额外功能 需求&#xff1a;当页面加载时&#xff0c;让元素将获得焦点 (autofocus在safari浏览器有兼容性) 操作dom&#xff1a;dom元素.focus() mounted() {this.$ref…

安装和配置OceanBase

安装和配置OceanBase 下面是安装和配置OceanBase&#xff08;jieyiobs集群&#xff09;的步骤&#xff1a; 1. 安装YUM工具&#xff08;如果尚未安装&#xff09; yum install -y yum-utils2. 添加OceanBase仓库 为了能从OceanBase的官方源安装软件&#xff0c;需要添加它的…

(delphi11最新学习资料) Object Pascal 学习笔记---第12章操作类(类方法和类数据)

第12章 操作类 ​ 在过去的几章中&#xff0c;你已经了解了 Object Pascal 语言面向对象的基础&#xff1a;类、对象、方法、构造函数、继承、后期绑定、接口等等。现在&#xff0c;我们需要进一步了解与类管理相关的一些更高级、更具体的语言特性。从类引用到类助手(class he…

Elasticsearch解决字段膨胀问题

文章目录 背景Flattened类型的产生Flattened类型的定义基于Flattened类型插入数据更新Flattened字段并添加数据Flattened类型检索 Flattened类型的不足 背景 Elasticsearch映射如果不进行特殊设置&#xff0c;则默认为dynamic:true。dynamic:true实际上支持不加约束地动态添加…

关于milvus go sdk运行时报9223372036854775807 (untvped int constant)overflows int问题

背景 在使用milvus go sdk去查询milvus服务中并列出所有集合的时候遇到一个int溢出问题&#xff0c;依据官方文档&#xff0c;具体代码如下 package localimport ("context""fmt""github.com/milvus-io/milvus-sdk-go/v2/client""log&quo…