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

news2025/1/22 9:23:06

一、初始化列表定义

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

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.coloradmin.cn/o/1165220.html

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

相关文章

tauri 访问静态资源,响应头为Content-Type:‘text/html‘

现象 报错&#xff1a; Error: THREE.FBXLoader: Unknown format. at FBXLoader.parse (index-f8291142.js:22050:15) at Object.onLoad (index-f8291142.js:22033:22) at index-f8291142.js:19769:20 使用threejs 加载fbx模型文件时&#xff0c;返回头中Content-…

《C++ Primer》第6章 函数(一)

参考资料&#xff1a; 《C Primer》第5版《C Primer 习题集》第5版 6.1 函数基础&#xff08;P182&#xff09; 典型的函数定义包括&#xff1a;返回类型&#xff08; return type &#xff09;、函数名字、0 个或多个形参&#xff08; parameter &#xff09;组成的列表、函…

使用HttpClient库的爬虫程序

使用HttpClient库的爬虫程序&#xff0c;该爬虫使用C#来抓取内容。 using System; using System.Net.Http; using System.Threading.Tasks; ​ namespace CrawlerProgram {class Program{static void Main(string[] args){// 创建HttpClient对象using (HttpClient client new…

数据结构 - 顺序表ArrayList

目录 实现一个通用的顺序表 总结 包装类 装箱 / 装包 和 拆箱 / 拆包 ArrayList 与 顺序表 ArrayList基础功能演示 add 和 addAll &#xff0c;添加元素功能 ArrayList的扩容机制 来看一下&#xff0c;下面的代码是否存在缺陷 模拟实现 ArrayList add 功能 add ind…

Linux多线程服务端编程:使用muduo C++网络库 学习笔记 第七章 muduo编程示例(上)

本章将介绍如何用muduo网络库完成常见的TCP网络编程任务。内容如下&#xff1a; 1.[UNP]中的五个简单协议&#xff0c;包括echo、daytime、time、discard、chargen等。 2.文件传输&#xff0c;示范非阻塞TCP网络程序中如何完整地发送数据。 3.Boost.Asio中的示例&#xff0c;…

新手学习两种不同的存储方式(不喜勿喷)

localStorage.setItem(sid,res.info.id)console.log(sid,res.info.id)sessionStorage.setItem(uid,res.info.id) sid和uid&#xff0c;也可以写其他的只来替代&#xff1b;而res.info.id是接口的数据可替换成自己的 一次性传的id值刷新页面就没有 永久性传的id 这是Javascript…

Linux——切换CUDA版本

一、查看本地cuda版本 cd /usr/local/ ls当前cuda为软连接&#xff0c;指向指定的cuda版本 stat cuda # 查看当前cuda状态信息二、切换CUDA版本 # 删除原有软连接 sudo rm -rf /usr/local/cuda # 建立需要切换的cuda软连接版本 sudo ln -s /usr/local/cuda-**.* /usr/l…

【GitLab、GitLab Runner、Docker】GitLab CI/CD 应用

安装Gitlab开源版 官方文档-安装Gitlab 使用Docker安装 sudo docker run --detach \--hostname gitlab.example.com \--env GITLAB_OMNIBUS_CONFIG"external_url http://${ip}:9999/; gitlab_rails[gitlab_shell_ssh_port] 8822;" \--publish 443:443 --publish 99…

Circos图绘制

Circos图其实是一个用途非常广泛的图形&#xff0c;可以用于表征基本上任何类型的数据&#xff0c;包括把我们常见的散点图、折线图和柱状图等都可以整合到Circos当中。特别是&#xff0c;Circos尤其适合用来描述生物信息学和基因组学的数据。 1.绘制Circos图 目前绘制Circos图…

单元测试一(理论)-云计算2023.11-云南农业大学

实验《 ECS数据管理实践-备份与恢复》 https://developer.aliyun.com/adc/scenario/7ad13e326c924d07a1ddb4e88cb26ce4 数据盘挂载到 /alidata&#xff0c;alidata改为自己姓名全拼&#xff0c;数据盘上创建文件test.txt&#xff0c;改为test接自己姓名全拼.txt&#xff0c;快…

根据Word模板,使用POI生成文档

突然想起来有个小作业&#xff1a;需要根据提供的Word模板填充数据。这里使用POI写了一个小demo验证下。 测试用模板&#xff1a; 执行结果 1.引入依赖坐标 <dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId&…

07、如何取出对象数组里的固定 key 值来拼成一个对象(以及对象与数组之间的转化)

1、数据情况&#xff1a; 其一、从后端拿到的数据为&#xff1a; let arr [1, 3, 7, 24] 其二、目标数据为(即&#xff1a;后台需要下发的数据)&#xff1a; {vlan_1: 1, vlan_3: 1, vlan_7: 1, vlan_24: 1} 2、操作过程&#xff1a; 其一、定义一个动态的 key 值来满足…

基于nodejs+vue客户管理管理系统

目 录 摘 要 I ABSTRACT II 目 录 II 第1章 绪论 1 1.1背景及意义 1 1.2 国内外研究概况 1 1.3 研究的内容 1 第2章 相关技术 3 2.1 nodejs简介 4 2.2 express框架介绍 6 2.4 MySQL数据库 4 第3章 系统分析 5 3.1 需求分析 5 3.2 系统可行性分析 5 3.2.1技术可行性&#xff1a;…

JAVA代码审计-cms综合篇

前言 JEECGv3.8。下载地址&#xff1a;GitHub - jeecgboot/jeecg at v3.8 java代码审计第一步&#xff1a;查看web.xml 一个重要的servlet&#xff1a;DispatcherServlet&#xff0c; <servlet><description>spring mvc servlet</description><servle…

MYSQL体系结构总结

&#xff08;笔记整理自b站马士兵教育课程&#xff09; MYSQL总体分为服务层和存储引擎层。 一、服务层 功能&#xff1a; 1、连接&#xff1a;管理连接&#xff0c;权限验证。 2、解析器&#xff1a;词法分析&#xff0c;语法分析。 3、优化器&#xff1a;执行计划生成…

node使用http模块

文章目录 前言一、创建http服务二、设置http的响应报文三、不同请求响应不同数据四、请求响应不同html文件1. 添加www文件夹2. js代码3. 效果 五、get和post请求的区别 前言 提示&#xff1a;这里可以添加本文要记录的大概内容&#xff1a; 一、创建http服务 // 1&#xff1a…

90 数组中的第K个最大元素

数组中的第K个最大元素 题解1 最小堆&#xff08;STL实现&#xff09;题解2 快排的partition思想题解3 手撸大根堆(记忆理解)参考link&#xff1a; 给定整数数组 nums 和整数 k&#xff0c;请返回数组中第 k 个最大的元素。 请注意&#xff0c;你需要找的是数组排序后的第 k…

告别菜鸟!快速精通ER图的绝招在这里!

当涉及到数据管理和数据库设计时&#xff0c;实体-关系图&#xff08;ER图&#xff09;无疑是最重要的工具之一。他们在数据模型设计过程中发挥着举足轻重的作用。但是&#xff0c;理解ER图并不是一项容易的任务。如果你对ER图感到困惑&#xff0c;我们提供了这一全面的指南&am…

Java语法 - 01

Java基础 Java 是一种广泛使用的高级编程语言&#xff0c;最初由Sun Microsystems于1995年发布。它被设计为具有简单、可移植和面向对象的特性&#xff0c;以满足跨平台应用程序开发的需求。以下是一些关于 Java 的简介&#xff1a; 跨平台性&#xff1a;Java 程序可以在不同…

Java学习笔记(六)——面向对象编程(基础)

一、类与对象 &#xff08;一&#xff09;类与对象的概念 &#xff08;二&#xff09;对象内存布局 ​编辑 对象分配机制 ​编辑 &#xff08;三&#xff09;属性/成员变量 &#xff08;四&#xff09;创建对象与访问属性 二、成员方法 &#xff08;一&#xff09;方法…