当前位置: 首页 > news >正文

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。

相关文章:

  • 【Algorithm】最容易理解的蒙特卡洛树搜索(Monte Carlo Tree Search,MCTS)算法
  • 华纳云:centos系统中怎么查看cpu信息?
  • 【智能座舱系列】- 深度解密小米Hyper OS,华为HarmonyOS区别
  • 【从0到1设计一个网关】过滤器链的实现---实现负载均衡过滤器
  • postgresql|数据库|SQL语句冲突的解决
  • 2023年CCF中国开源大会“大模型时代的智能化软件工程新范式”分论坛成功举行...
  • zookeeper安装配置
  • 基于nodejs+vue客户管理管理系统
  • 天拓四方分享:企业安全生产管控系统的构建、实施与优化
  • ip划分与私公网ip、ip的传递
  • 供应链ERP之合同:创建、修订与模板
  • 【PyQt学习篇 · ⑥】:QWidget - 事件
  • 数据结构详细笔记——二叉树
  • 数据分析师的工作内容、工作目标、必备工具、能力模型
  • linux查看文件夹使用情况以及查看文件大小
  • __proto__ 和 prototype的关系
  • 4个实用的微服务测试策略
  • Apache的80端口被占用以及访问时报错403
  • C++入门教程(10):for 语句
  • django开发-定时任务的使用
  • E-HPC支持多队列管理和自动伸缩
  • Github访问慢解决办法
  • IE报vuex requires a Promise polyfill in this browser问题解决
  • JavaScript 奇技淫巧
  • Javascript弹出层-初探
  • Java新版本的开发已正式进入轨道,版本号18.3
  • js算法-归并排序(merge_sort)
  • Logstash 参考指南(目录)
  • MySQL-事务管理(基础)
  • Python学习之路16-使用API
  • Quartz初级教程
  • Spark in action on Kubernetes - Playground搭建与架构浅析
  • SQLServer之索引简介
  • vuex 笔记整理
  • Web标准制定过程
  • 阿里云爬虫风险管理产品商业化,为云端流量保驾护航
  • 百度小程序遇到的问题
  • 从零开始学习部署
  • 高程读书笔记 第六章 面向对象程序设计
  • 工作中总结前端开发流程--vue项目
  • 简单易用的leetcode开发测试工具(npm)
  • 新版博客前端前瞻
  • ​520就是要宠粉,你的心头书我买单
  • #我与Java虚拟机的故事#连载17:我的Java技术水平有了一个本质的提升
  • (2)(2.10) LTM telemetry
  • (delphi11最新学习资料) Object Pascal 学习笔记---第2章第五节(日期和时间)
  • (MonoGame从入门到放弃-1) MonoGame环境搭建
  • (二)七种元启发算法(DBO、LO、SWO、COA、LSO、KOA、GRO)求解无人机路径规划MATLAB
  • (附源码)ssm高校实验室 毕业设计 800008
  • (实战)静默dbca安装创建数据库 --参数说明+举例
  • (四)【Jmeter】 JMeter的界面布局与组件概述
  • .【机器学习】隐马尔可夫模型(Hidden Markov Model,HMM)
  • .form文件_SSM框架文件上传篇
  • .net 4.0发布后不能正常显示图片问题
  • .net core 实现redis分片_基于 Redis 的分布式任务调度框架 earth-frost