C++之初始化列表详细剖析

一、初始化列表定义

初始化列表:以一个冒号开始,接着是一个以逗号分隔的数据成员列表,每个"成员变量"后面跟一个放在括号中的初始值或表达式。

class Date
{
public:Date(int year, int month, int day): _year(year), _month(month)//初始化列表, _day(day){}
private:int _year;int _month;int _day;
};

二、初始化列表内在作用的剖析

不知道大家有没有想过这样一个问题,成员函数明明可以在函数内部对成员变量进行赋值,那为什么还要搞出初始化列表这个东西呢?这个时候就需要我们对初始化列表有一个更加深刻的理解了。

我们知道,在一个类被设计出来的时候,它里面定义的成员变量只是变量的声明,没有为其分配空间。我们也知道,类定义出一个对象是在主函数中定义的,而创建出来的这个对象其中的成员变量其实是在初始化列表中定义的。那么假设我们创建出来的类的成员变量中含有引用类型或者是被const修饰时(引用类型和const修饰的变量在定义时就必须为其赋初始值),就像下面这个代码:

 如果我们定义的类内部的成员变量中含有引用类型或者是被const修饰,而在成员函数体内部再对其赋初始值,就相当于_ref和_n两个变量定义和赋初始值分离了,但我们明确地知道引用类型或者是被const修饰的变量在定义时就必须为其赋初始值,所以编译器会报未初始化的错误。上面图片中的代码还可以写的更明确一点,就相当于下面这种形式:

 五个成员变量全部定义和赋初始值分开,一般的内置类型是支持这种行为的。就像是这样:

int main()
{int a;a = 10;//可以int& n;n = a;//报错const int m;m = 10;//报错return 0;
}

所以正确的方法应该是:类内部的成员变量中含有引用类型或者是被const修饰时,引用类型或者是被const修饰的成员变量必须用初始化列表赋初值(定义时就赋初值)。

class Date
{
private:int _year;int _month;int _day;int& _ref;const int _n;public:Date(int year, int month, int day):_year(),_month(),_day(),_ref(month),_n(1){this->_year = year;this->_month = month;this->_day = day;}
};

三、类中成员变量含有自定义类型的情况

很好理解,自定义也必须使用初始化列表进行初始化,如果自定义类型没有显示地调用初始化列表,那么自定义类型就会去调用它的默认构造函数,如果没有默认构造函数,就会编译报错。

#include <iostream>
using namespace std;class A
{
private:int _a;public:A(int a = 0){this->_a = a;}
};class Date
{
private:int _year;int _month;int _day;A aa;int& _ref;const int _n;public:Date(int year, int month, int day):_year()  //aa没有显示地调用初始化列表,会去调用它的默认构造函数, _month()//剩下的三个成员没有写出来定义,但是它也会定义,只是内置类型给的随机值, _day()  //自定义类型会去调用它的默认构造函数,_ref(month),_n(1){this->_year = year;this->_month = month;this->_day = day;}
};//编译没有报错
int main()
{Date d1(2023, 11, 2);return 0;
}

 _a被初始化为了0。还是上面这段代码,如果将A(int a = 0)改成A(int a),编译就会报错,因为没有合适的默认构造函数。

所以自定义类型在使用初始化列表的时候,建议要显示地传参去调用指定的构造函数。

四、初始化列表使用的建议以及小点

尽量使用初始化列表初始化,因为不管你是否使用初始化列表,对于自定义类型成员变量,
一定会先使用初始化列表初始化。
但是我们能不能什么地方都用初始化而都不在函数体内部赋初始值呢?答案是不行的。初始化列表可以解决百分之九十的问题,但对于一些像判断之类的语句还是要放在函数体内部的。像下面这个例子:
class Date
{
private:int _year;int _month;int _day;int* _aa;public:Date(int year, int month, int day):_year(year)  //aa没有显示地调用初始化列表,会去调用它的默认构造函数, _month(month)//剩下的三个成员没有写出来定义,但是它也会定义,只是内置类型给的随机值, _day(day)  //自定义类型会去调用它的默认构造函数,_aa(new int [10]){if (_aa == nullptr){perror("new fail");exit(-1);}}~Date(){delete[] _aa;}
};int main()
{Date d1(2023, 11, 2);return 0;
}

这里有一个小点需要注意:. 成员变量在类中声明次序就是其在初始化列表中的初始化顺序,与其在初始化列表中的先后次序无关。

class A
{
public:A(int a):_a1(a), _a2(_a1){}void Print() {cout << _a1 << " " << _a2 << endl;}
private:int _a2;int _a1;
};int main() 
{A aa(1);aa.Print();
}

上面代码_a2比_a1先声明,所以_a2先初始化,用_a1初始化_a2,此时_a1为随机值,所以初始化完_a2为随机值,再用1初始化_a1,_a1为1。

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

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

相关文章

OpenCV快速入门:图像分析——图像分割和图像修复

文章目录 前言一、图像分割1.1 漫水填充法1.1.1 漫水填充法原理1.1.2 漫水填充法实现步骤1.1.3 代码实现 1.2 分水岭法1.2.1 分水岭法原理1.2.2 分水岭法实现步骤1.2.3 代码实现 1.3 GrabCut法1.3.1 GrabCut法原理1.3.2 GrabCut法实现步骤1.3.3 代码实现 1.4 Mean-Shift法1.4.1…

论文阅读 (106):Decoupling maxlogit for out-of-distribution detection (2023 CVPR)

文章目录 1 概述1.1 要点1.2 代码1.3 引用 2 预备知识3 方法3.1 MaxLogit3.2 改进MaxCosine和MaxNorm3.3 DML 1 概述 1.1 要点 题目&#xff1a;解耦最大logit分布外检测 (Decoupling maxlogit for out-of-distribution detection) 方法&#xff1a; 提出了一种心机基于log…

多级缓存快速上手

哈喽~大家好&#xff0c;这篇来看看多级缓存。 &#x1f947;个人主页&#xff1a;个人主页​​​​​ &#x1f948; 系列专栏&#xff1a;【微服务】 &#x1f949;与这篇相关的文章&#xff1a; JAVA进程和线程JAVA进程和线程-CSDN博客Http…

不做机器视觉工程师,转行,转岗的建议与想法

正所谓外行看热闹&#xff0c;内行看门道。提前咨询前辈们&#xff0c;多问问&#xff0c;多看看。要做就做&#xff0c;一定要提前做好防范。 无论你是要转行或者是转岗&#xff0c;看你有没有本钱和试错成本 有些人&#xff0c;家庭好&#xff0c;可以一直去试错和从头再来。…

无线WiFi安全渗透与攻防(国外篇):使用 Aircrack-ng 破解 WEP 密码

使用 Aircrack-ng 破解 WEP 密码 使用 Aircrack-ng 破解 WEP 密码一. 用 Aircrack-ng 破解 WEP 密码 - 背景知识网卡与网卡芯片WEP 加密协议WEP 所使用的身份认证协议二. 使用 Aircrack-ng 破解 WEP 密码 - 破解原理破解机理三. 使用 Aircrack-ng 破解 WEP 密码 - aircrack-ng …

学习.NET验证模块FluentValidation的基本用法(续1:其它常见用法)

FluentValidation模块支持链式验证方法调用&#xff0c;也就是说&#xff0c;除了 RuleFor(r > r.UserName).NotEmpty()调用方式之外&#xff0c;还可以将对单个属性的多种验证函数以链式调用方式串接起来&#xff0c;比如UserName属性不能为空&#xff0c;长度在5~10之间&a…

__attribute__((constructor))用法解析

__attribute__((constructor))是GCC和兼容的编译器中的一个特性&#xff0c;用于指示编译器将一个函数标记为在程序启动时自动执行的初始化函数。 同样的还有__attribute__((destructor))在main()函数后调用。 当你在一个函数声明或定义前加上__attribute__((constructor))属…

浅谈 Guava 中的 ImmutableMap.of 方法的坑

作者&#xff1a;明明如月学长&#xff0c; CSDN 博客专家&#xff0c;大厂高级 Java 工程师&#xff0c;《性能优化方法论》作者、《解锁大厂思维&#xff1a;剖析《阿里巴巴Java开发手册》》、《再学经典&#xff1a;《EffectiveJava》独家解析》专栏作者。 热门文章推荐&…

vue项目下.env.development环境变量配置文件

.env.development 文件是一个用于开发环境配置的文件。在许多应用程序中&#xff0c;开发环境和生产环境具有不同的配置需求。.env.development 文件允许你在开发环境中定义特定的环境变量和配置选项。 一般来说&#xff0c;.env.development 文件用于存储开发环境相关的配置信…

国自然项目基金撰写的隐藏技巧、范例分析及提交前的自我审查

目录 一、基金项目申请要求、重点及项目介绍 二、基金的撰写技巧 三、基金撰写的隐藏技巧 四、范例分析及提交前的自我审查 更多应用 基金项目申请需要进行跨学科的技术融合&#xff0c;申请人需要与不同领域结合&#xff0c;形成多学科交叉的研究。基金项目申请在新时期更…

由红黑树引出的HashMap扩容机制的思考

红黑树是什么&#xff1f; 三大特点&#xff1a; 根节点是黑色&#xff0c;叶节点是不存储数据的黑色空节点 任何相邻的两个节点不能同时为红色 任意节点到其可到达的节点间包含相同数量的黑色节点 联想&#xff1a;Java HashMap底层红黑树原理 HashMap基于哈希表Map接口实…

快速掌握Pyqt5的三种主窗口

PyQt5是一个强大的跨平台GUI框架&#xff0c;它提供了多种不同类型的主窗口类&#xff0c;以满足不同的应用需求。下面是PyQt5中最常见的几种主窗口类型及其创建方式的简介&#xff1a; 1. QMainWindow QMainWindow是用于创建具有菜单栏、工具栏、状态栏和中心窗口部件&#…

内存池 示例一

内存池是一种管理内存分配和释放的技术&#xff0c;用于优化内存的使用效率。它通过预先分配一块内存区域&#xff0c;并将其划分为多个较小的块&#xff08;内存块池&#xff09;&#xff0c;然后按需分配这些内存块来减少内存碎片化和频繁的系统调用。这些内存块可以是相同大…

Centos7.9配置nfs共享及rsync同步

客户需求对oracle数据库做一个跨机房的备份&#xff0c;原环境已做rman备份和每天expdp全库导出&#xff0c;远端只有虚拟化环境&#xff0c;可提供一个虚拟机&#xff0c;2个机房间网络互通。 首先配置nfs服务端 查看操作系统版本 [rootnas199 ~]# more /etc/redhat-relea…

Python面经【1】

一、协程的相关概念 协程&#xff08;又称微线程&#xff09;运行在线程之上&#xff0c;更加轻量级&#xff0c;协程并没有增加线程总数&#xff0c;只是在线程的基础上通过分时复用的方式运行多个协程&#xff0c;大大提高工程效率。 协程的特点&#xff1a; 轻量级&#…

WordPress站点屏蔽过滤垃圾评论教程(Akismet反垃圾评论插件)

前段时间我的WordPress站点经常收到垃圾评论的轰炸&#xff0c;严重时一天会收到几十条垃圾评论。我这个小破站一没啥流量&#xff0c;二又不盈利&#xff0c;实在是不太理解为啥有人要这么执着地浪费资源在上面。 Akismet反垃圾评论插件 其实用了 Akismet 反垃圾评论插件后&a…

快速掌握Pyqt5的6种按钮

在PyQt5中&#xff0c;按钮是构建用户界面的基本元素之一&#xff0c;用于执行命令、启动功能或触发事件。PyQt5提供了多种类型的按钮&#xff0c;每种都适用于不同的场景和需求。 1. QPushButton QPushButton 是最常用的按钮类型&#xff0c;适用于大多数情况&#xff0c;如…

ARCore:在Android上构建令人惊叹的增强现实体验

ARCore&#xff1a;在Android上构建令人惊叹的增强现实体验 一、 AR 介绍1.1 AR技术简介1.2 AR技术原理1.3 AR技术应用领域 二、Google的增强现实平台ARCore2.1 ARCore简介2.2 ARCore API介绍2.3 ARCore API使用示例 三、总结 一、 AR 介绍 增强现实 Augmented Reality&#x…

【算法-字符串2】替换空格 + 反转单词

今天&#xff0c;带来字符串相关算法的讲解。文中不足错漏之处望请斧正&#xff01; 理论基础点这里 1. 替换空格 题目描述&#xff1a;请实现一个函数&#xff0c;把字符串 s 中的每个空格替换成"%20"。 来源&#xff1a;力扣&#xff08;LeetCode&#xff09; 难…

Lettuce使用详解

简介特点连接池连接池特点连接池管理连接池优势连接池配置参数 监控常用监控工具通过JMX监控通过Prometheus监控 代码示例拓展springboot中通过jmx上报到Prometheus代码示例更多Redis相关内容 简介 Lettuce 是一个高级的、线程安全的 Redis 客户端&#xff0c;用于与 Redis 数…