【C++】初始化列表

news2024/12/28 5:12:39

前言:这个知识点的细节比较多,且有些细节不太容易理解,要做好准备哟👻

Ⅰ.构造函数的不完美😭

初始化列表,顾名思义,用列表一样的格式将其初始化。

🤔奇怪啊,构造函数的不是可以初始化嘛?为什么C++还要引入初始化列表?

唉,因为这个构造函数它在某些方面不太好使啊!

在介绍初始化列表之前,我先来把构造函数的缺陷指出来,从而让我们意识到:世界需要初始化列表。

关于构造函数的不完美,这里列出2点:

1.当自定义类型成员没有默认构造函数时,会出现一种很尴尬的场面:

class Time
{
public:
    Time(int time)
    {
        _time = time;
    }
private:
    int _time;
};
​
class Date
{
public:
    Date(int day, int time)
    {
        _t = time;
        _day = day;
    }
private:
    int _day;
    Time _t;  //默认构造函数会调用自定义类型的Time(int time)
};
​
int main()
{
    Date d1(1,1);
    return 0;
}

为啥尴尬?

示例化d1时,会调d1的默认构造函数(编译器自己生成的),它对于内置类型 _year不做处理,

但对于自定义类型 _t,会调用它的构造函数,此时我们自己写了,编译器不再自动生成默认的。

然而,这个Time是需要传参的,可d1并没有传参过去。

所以会编译失败。

2.没法给const常量、引用类型的成员变量初始化。

举个const常量的例子。

const常量,在声明的同时,必须初始化。

int main() {
    int a = 0;
    const int b;  //没初始化
    return 0;
}

它就必须得写成这样:

const int b = 0(初始值);

而构造函数没法让const常量初始化:

class Date {
public:
    Date(int year, int month, int day) {
        this->_year = year;
        this->_month = month;
        this->_day = day;
    }
private:
    const int _year;     //假如_year设定为2023,那它又该在哪初始化呢?
    int _month;         //这里是声明,是不可以初始化的!
    int _day;
};
int main() {
​
    return 0;
}

在Date构造函数里是没法初始化变量的。

因为类就是一张造房子的图纸,它实际并没开空间!

而初始化一个变量,是需要开空间,来保存值的。

Ⅱ.初始化列表✨

1.格式

构造函数是在函数体内初始化的,而初始化列表是在体外。

以一个冒号开始,接着是一个以逗号分隔的数据成员列表,

每个"成员变量"后面跟一个放在括号中的初始值或表达式。

be like this:

Date(int year, int month, int day)
        :_year(year)
        ,_month(month)  
        ,_day(day)
    {}

Date(int month, int day)
        :_year(2023)
        ,_month(month)   //用几个参数就传几个
        ,_day(day)
    {}

Date()
        :_year(2023)
        , _month(1)
        ,_day(1)
    {}

2.用初始化列表 解决 构造函数的问题

刚刚我们指出,自定义类型成员(前提是没有默认构造函数)、const常量成员,都没法被构造函数初始化。

现在换上初始化列表试试:

a. 自定义类型成员
class Time
{
public:
    Time(int time)
    {
        _time = time;
    }
private:
    int _time;
};
​
class Date
{
public:
    Date(int day, int time)
        :_t(time)        //自定义类型用初始化列表
    {
        _day = day;
    }
private:
    int _day;
    Time _t; 
};
​
int main()
{
    Date d1(1,1);
    return 0;
}

成功初始化:

b. const常量成员
class Date {
public:
    Date(int month, int day) 
        :_year(2023)
    {
        this->_month = month;
        this->_day = day;
    }
private:
    const int _year;    
    int _month;         
    int _day;
};
​
int main() {
    Date d1(1, 1);   //d1、d2、d3的_year都是2023
    Date d2(2,2);
    Date d3(3,3);
    return 0;
}

成功初始化:

3.说明

1.每个成员变量在初始化列表中只能出现一次(初始化只能初始化一次)

这区别于构造函数,构造函数体内可以多次赋值。

//构造函数✅:

class Date {
public:
    Date(int year, int month, int day){
        _year = year;
        _month = month;
        _day = day;
        _year = 2000;  //多次赋值
    }
private:
    int _year;    
    int _month;        
    int _day;
};
​
int main()
{
    Date d1(1,1);  //d1初始化的结果为2000-1-1,而非2023-1-1
    return 0;
}

//初始化列表❎,编译报错:

class Date {
public:
    Date(int year, int month, int day)
        :_year(year)
        ,_month(month)
        ,_day(day)
        ,_year(2000) //多次赋值
    {}
    
private:
    int _year;    
    int _month;        
    int _day;
};

2.类中包含以下成员,必须放在初始化列表位置进行初始化:

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

3.尽量使用初始化列表初始化。

其实,无论是用初始化列表,还是函数体内初始化,对于内置类型都是无所谓的。

但对于自定义类型成员变量,一定要使用初始化列表初始化。不然连编译都通过不了。

4.初始化列表中的初始化顺序:

为成员变量在类中的声明次序

与其在初始化列表中的先后次序无关。

class Date {
public:
    Date() 
        :_month(1)   //不是这个次序
        ,_day(1)
        ,_year(2023)
    {
    }
private:     //看的是这里声明的次序
    int _year;    
    int _month;         
    int _day;
};

不过,还是建议 声明的顺序和初始化列表的顺序 保持一致,不易错🥰


初始化列表就讲到这里。

可以发现,初始化列表 并不是 来取代构造函数的,

它是来辅助构造函数,让初始化变量 更灵活好用的。

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

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

相关文章

DOCKER 部署 webman项目

# 设置基础镜像 FROM php:8.2-fpm# 安装必要的软件包和依赖项 RUN apt-get update && apt-get install -y \nginx \libzip-dev \libpng-dev \libjpeg-dev \libfreetype6-dev \&& rm -rf /var/lib/apt/lists/*# 安装 PHP 扩展 RUN docker-php-ext-configure gd …

Uniapp笔记(八)初识微信小程序

一、微信小程序基本介绍 1、什么是微信小程序 微信小程序简称小程序,英文名Mini Program,是一种不需要下载安装即可使用的应用,它实现了应用“触手可及”的梦想,用户扫一扫或搜一下即可打开应用 小程序是一种新的开放能力&#…

嵌入式学习之指针

今天周天,主要对linux系统编程的知识进行了学习,但是很多精华还是没有学到位,重点的学习内容是把linux 中open,write,lseek,close的相关操作进行了学习。其次再次把函数指针,数组指针,指针函数,指针数组进行…

线性代数的学习和整理13: 函数与向量/矩阵

目录 1 函数与 向量/矩阵 2 函数的定义域,值域,到达域 3 对应关系 1 函数与 向量/矩阵 下面两者形式类似,本质也类似 函数的: axy ,常规函数里,a,x,y 一般都是单个数矩阵: AXY &a…

[管理与领导-54]:IT基层管理者 - 扩展技能 - 1 - 时间管理 -1- 时间管理的基本理念和五大原则

前言: 管理学大师彼得 德鲁克曾说过:“不能管理时间,便什么也不能管理” 。论语中说:逝者如斯 夫!不舍昼夜。时间对任何一个人来说都是十分重要的,对于惜时如金的管理者来说更是如此。 时间也是一种资源,对所有的人…

TIM输入捕获笔记 (计算编码电机的频率和占空比)

1. 输入捕获简介 IC (Input Capture) 输入捕获输入捕获模式下,当通道输入引脚出现指定电平跳变时,当前CNT的值将被锁存到CCR中,可用于测量PWM波形的频率、占空比、脉冲间隔、电平持续时间等参数每个高级定时器和通用定时器都拥有4个输入捕获…

Docker网络原理及案例详解

文章目录 简介Docker网络产生的过程Docker network的作用网络模式网络模式---bridge网络模式---host网络模式---none 自定义网络 简介 Docker网络实现容器之间通信和连接外部网络的功能,主要的网络连接方式有桥接网络(Bridge Network、主机网络(Host Ne…

【LeetCode75】第三十九题 二叉树的右视图

目录 题目: 示例: 分析: 代码: 题目: 示例: 分析: 题目给我们一棵二叉树,让我们返回站在二叉树右边从上到下看到的节点。 那实际上就是要我们对二叉树进行层序遍历&#xff0c…

CS144(2023 Spring)Lab 0:networking warmup(环境搭建 webget bytestream)

文章目录 前言其他笔记相关链接 1. Set up GNU/Linux on your computer2. Networking by hand3. Writing a network program using an OS stream socket3.1 Linux配置3.2 C规范3.3 Writing webget3.3.1 实现3.3.2 测试 4. An in-memory reliable byte stream4.1 思路分析4.2 代…

《C和指针》笔记14: 作用域和存储类型总结(例子说明)

文章目录 题目答案解释总结 本文是作用域和存储类型的总结,以一个例子来说明,如果不看解释可以很直接地回答每一条语句的作用域和存储类型,那么说明已经很熟练地掌握这个知识点了。 关于作用域和存储类型可以参考我前面的博客: …

LeetCode-56-合并区间

题目描述: 以数组 intervals 表示若干个区间的集合,其中单个区间为 intervals[i] [starti, endi] 。请你合并所有重叠的区间,并返回 一个不重叠的区间数组,该数组需恰好覆盖输入中的所有区间 。 可以使用 LinkedList,…

Cadence+硬件每日学习十个知识点(46)23.8.26 (运算放大器)

文章目录 1.电压跟随器的输入和输出是一样的,但是输入的是电压带有高阻抗,输出的电压带有低阻抗。2.比较器的迟滞(这个电阻)3.运放的压摆率4.运放-轨到轨5.输入失调电压Vos(选一个低的器件就行,对于5V&…

Batbot电力云平台在智能配电室中的应用

智能配电室管理系统是物联网应用中的底层应用场景,无论是新基建下的智能升级,还是双碳目标下的能源管理,都离不开智能配电运维对传统配电室的智慧改造。Batbot智慧电力(运维)云平台通过对配电室关键电力设备部署传感器…

【学习笔记】求解线性方程组的G-S迭代法

求解线性方程组的G-S迭代法 // 运行不成功啊function [x,k,index] Gau_Seid(A,b,ep,it_max) % 求解线性方程组的G-S迭代法,其中 % A为方程组的系数矩阵 % b为方程组的右端项 % ep为精度要求,省缺为1e-5 % it_max为最大迭代次数,省缺为100 % …

1. 深度学习介绍

1.1 AI地图 ① 如下图所示,X轴是不同的模式,最早的是符号学,然后概率模型、机器学习。Y轴是我们想做什么东西,感知是我了解这是什么东西,推理形成自己的知识,然后做规划。 ② 感知类似我能看到前面有个屏…

微前端开发

微前端介绍 微前端的概念是由ThoughtWorks在2016年提出的,它借鉴了微服务的架构理念,核心在于将一个庞大的前端应用拆分成多个独立灵活的小型应用,每个应用都可以独立开发、独立运行、独立部署,再将这些小型应用融合为一个完整的…

【大数据】Linkis:打通上层应用与底层计算引擎的数据中间件

Linkis:打通上层应用与底层计算引擎的数据中间件 1.引言2.背景3.设计初衷4.技术架构5.业务架构6.处理流程7.如何支撑高并发8.用户级隔离度和调度时效性9.总结 Linkis 是微众银行开源的一款 数据中间件,用于解决前台各种工具、应用,和后台各种…

【git进阶使用】 告别只会git clone 学会版本控制 ignore筛选 merge冲突等进阶操作

git使用大全 基本介绍git 快速上手一 环境安装(默认已安装)二 远程仓库克隆到本地1 进入rep文件夹目录2 复制远程仓库地址3 git clone克隆仓库内容到本地4 修改后版本控制4.1 修改文件4.2 git status查看版本库文件状态4.3 git add将文件加入版本库暂存区…

NEOVIM学习笔记

GitHub - blogercn/nvim-config: A pretty epic NeoVim setup 一直使用vim,每次到了新公司都要配置半天,而且常常配置失败,很多插件过期不好用。偶然看到别人的NEO VIM,就试着用了一下,感觉还不错。 用来开发和阅读C代…

使用树莓派Pico、DHT11和SSD1306搭建一个温度湿度计(只使用官方库,以及官方案例代码的错误之处和解决方案)

最近想树莓派 Pico、DHT11 温湿度传感器和 SSD1306 OLED 屏幕做一个温度湿度计,树莓派官方案例也分别有这两个设备的案例,我就想做个简单的温度湿度计作为学习微控制器的开始,结果遇到了一个大坑,所以写本文记录一下整个过程。 本…