【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:
    // 使用初始化列表来初始化_age
    Student(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++就讲解到这啦,如果你觉得写的不错的话,可以给个一键三连,点赞,关注+收藏,若有不足,欢迎各位在评论区讨论。  

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

k8s endpoint

Endpoint Service 并不是和 pod 直接相连的&#xff0c;Endpoint 介于两者之间。Endpoint 资源就是暴露一个服务的 IP 地址和端口的列表。 虽然在 spec 服务中定义了 pod 选择器&#xff0c;但在重定向传入连接时不会直接使用它。选择器用于构建 IP 和端口列表&#xff0c;然…

Pikachu 靶场 SQL 注入通关解析

前言 Pikachu靶场是一种常见的网络安全训练平台&#xff0c;用于模拟真实世界中的网络攻击和防御场景。它提供了一系列的实验室环境&#xff0c;供安全专业人士、学生和爱好者练习和测试他们的技能。 Pikachu靶场的目的是帮助用户了解和掌握网络攻击的原理和技术&#xff0c;…

网络基础_01

1.网络通信过程 1.1架构 c/s架构 c:client 服务器 s:server 客户端 客户端&#xff1a;安装在你电脑上的qq&#xff0c;浏览器(360浏览器、chrome浏览器、IE浏览器等)&#xff0c;当我们使用qq发送消息的时候&#xff0c;消息先发送到了腾讯&#xff0c;然后腾讯在转发到你朋友…

目标检测实战(八): 使用YOLOv7完成对图像的目标检测任务(从数据准备到训练测试部署的完整流程)

文章目录 一、目标检测介绍二、YOLOv7介绍三、源码/论文获取四、环境搭建4.1 环境检测 五、数据集准备六、 模型训练七、模型验证八、模型测试九、错误总结9.1 错误1-numpy jas mp attribute int9.2 错误2-测试代码未能跑出检测框9.3 错误3- Command git tag returned non-zero…

项目经理之路:裁员与内卷下的生存策略

作为一名项目经理&#xff0c;身处这个充满挑战与机遇的行业中&#xff0c;今年所面临的裁员潮和内卷化趋势无疑给我的工作带来了前所未有的压力。然而&#xff0c;正是这些压力和挑战&#xff0c;让我们更加深刻地思考了在这个快速变化的时代中&#xff0c;我们项目经理应该如…

DHCP动态主机配置协议

DHCP概述 DHCP是什么 DHCP&#xff1a;Dynamic Host Configuration Protocol&#xff1a;动态主机配置协议DHCP是一种集中对用户IP地址进行动态管理和配置的技术 DHCP作用&#xff1a; 作用&#xff1a;实现IP地址的动态分配和集中管理优势&#xff1a;避免手工配置IP地址&…

孟德尔随机化一区嘎嘎乱杀!| 孟德尔随机化周报(4.24-5.7)

孟德尔随机化,Mendilian Randomization&#xff0c;简写为MR&#xff0c;是一种在流行病学领域应用广泛的一种实验设计方法&#xff0c;利用公开数据库就能轻装上阵写文章&#xff0c;甚至是高质量的论文。 孟德尔随机化通过引入一个称之为工具变量的中间变量&#xff0c;来分析…

利用香港多IP服务器优化网站访问速度的关键策略?

利用香港多IP服务器优化网站访问速度的关键策略? 随着数字化时代的不断发展&#xff0c;网站的全球访问速度成为企业吸引用户、提升竞争力的重要因素。特别对于跨国企业而言&#xff0c;如何确保全球用户都能享受到稳定快速的访问体验显得尤为重要。在这一背景下&#xff0c;…

信号和槽的使用

&#x1f40c;博主主页&#xff1a;&#x1f40c;​倔强的大蜗牛&#x1f40c;​ &#x1f4da;专栏分类&#xff1a;QT❤️感谢大家点赞&#x1f44d;收藏⭐评论✍️ 目录 一、连接信号和槽 二、查看内置信号和槽 三、通过 Qt Creator 生成信号槽代码 一、连接信号和槽 …

什么是RSocket?它有哪些优势?

在传统Web应用开发过程中&#xff0c;我们都是基于HTTP协议实现请求-响应式的交互方式。这种交互方案很简单&#xff0c;但不够灵活&#xff0c;也无法应对所有的响应式应用场景。那么&#xff0c;有没有在网络协议层上提供更加丰富的交互方式呢&#xff1f;答案是肯定的&#…

从“山寨的”MTK芯片发展历程 同类芯片比较基础常识 如何简单识别mtk机型

联发科技&#xff08;MediaTek Inc.简称“联发科” &#xff0c;联发科起家于CD-ROM芯片&#xff0c;直接将DVD内分别承担视频和数字解码功能的两颗芯片整合到了一颗芯片上&#xff0c;并提供相应的软件方案。并一度占据大陆DVD市场60%的芯片供应量&#xff01;他将图像处理、M…

《Boosting Object Detection with Zero-Shot Day-Night Domain Adaptation》2024CVPR

域不变特征:是指在不同的数据域或环境下,特征能够保持不变或具有一定程度的鲁棒性。实现域不变特征可以在许多计算机视觉和机器学习任务中具有重要的作用,特别是在涉及跨域或跨环境的应用场景中。 以下是一些常用的实施域不变特征的方法: 1. 数据归一化:通过将数据进行归一…

uniapp h5 配置代理服务器

"devServer": {"disableHostCheck": true,"proxy": {"/api": {// 需要被代理的后台地址"target": "http://自己的地址","changeOrigin": true,"secure": false,"pathRewrite": {&q…

LLMs应被视为一种文字计算器?

编者按&#xff1a;当前&#xff0c;大语言模型已经成为自然语言处理领域的热点。LLMs 是否真的“智能”&#xff1f;它们又为我们带来了哪些启发&#xff1f;针对这些问题&#xff0c;Darveen Vijayan 为我们带来了这篇引人深思的文章。 作者主要阐释了两个观点&#xff1a;第…

WCF 通信三种模式 请求与答复、单向、双工通信

WCF 通信三种模式 请求与答复 默认模式单向双工 请求与答复 [OperationContract] string GetInfo(string id); [OperationContract] void Getxxx();即使返回值是void 也属于请求与答复模式。 缺点&#xff1a;如果用WCF在程序A中上传一个2G的文件&#xff0c;那么要想执行程…

【设计模式】JAVA Design Patterns——Abstract Factory(抽象工厂模式)

&#x1f50d;目的 提供一个用于创建相关对象家族的接口&#xff0c;而无需指定其具体类 &#x1f50d;解释 真实世界例子 要创建一个王国&#xff0c;我们需要具有共同主题的对象。精灵王国需要精灵国王、精灵城堡和精灵军队&#xff0c;而兽人王国需要兽人国王、兽人城堡和兽…

部署YUM仓库及 NFS共享服务

YUM仓库服务 部署YUM软件仓库 使用YUM工具管理软件包 一、YUM概述 1.YUM (Yellow dog Updater Modified) 基于RPM包构建的软件更新机制可以自动解决依赖关系所有软件包由集中的YUM软件仓库提供 2. 准备安装源3-1 2.1 软件仓库的提供方式 FTP服务:ftp://..HTTP服务:htt…

常见加解密算法03 - RC4逆向认识

各位聪明绝顶&#xff0c;才高八斗的读者们你们好&#xff01;今天我们主要讨论编译之后的RC4算法识别。 题外话&#xff0c;之前看到一个蛋疼的小知识&#xff0c;说“势”这个字最好不好查词典释义。我是很好奇的&#xff0c;果然后来无法直视势不可挡这个成语。 言归正传&am…

网络安全之OSPF进阶

该文针对OSPF进行一个全面的认识。建议了解OSPF的基础后进行本文的一个阅读能较好理解本文。 OSPF基础的内容请查看&#xff1a;网络安全之动态路由OSPF基础-CSDN博客 OSPF中更新方式中的触发更新30分钟的链路状态刷新。是因为其算法决定的&#xff0c;距离矢量型协议是边算边…

【微信小程序开发】深入探索事件绑定、事件冒泡、页面跳转的逻辑实现

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者简介&#xff1a;景天科技苑 &#x1f3c6;《头衔》&#xff1a;大厂架构师&#xff0c;华为云开发者社区专家博主&#xff0c;…