在C++中,成员变量必须在对象构造完成前初始化,但初始化的方式有多种...

devtools/2025/2/4 8:26:04/

在C++中,成员变量必须在对象构造完成前初始化,但初始化的方式可以有多种,具体取决于成员变量的类型和设计需求。以下是C++中成员变量初始化的规则和相关机制:


1. 成员变量必须初始化

  • 如果成员变量是基本类型(如 intdouble 等)类类型,未显式初始化时,它们的值是未定义的(除非是全局或静态变量,会被默认初始化为零值)。
  • 如果成员变量是引用类型常量成员(const,则必须在成员初始化列表中被显式初始化,否则会导致编译错误。
    常量成员必须在成员初始化列表中进行显式初始化的原因是很明显的,因为它一旦初始化完成,它的值就不能被修改了,假如编译器允许它不用被显式初始化,那么它在完成初始化后就有一个不确定的值作为其初始化值,而它一旦完成初始化,那么其值就不能被修改了,所以它就只能永远保持一个不确定的值,这样的常量对于我们是没有任何意义的,所以它必须在成员初始化列表中被显示初始化。
    而至于为什么引用成员也要在成员初始化列表中被显式初始化,详见 https://blog.csdn.net/wenhao_ir/article/details/145422877

2. 初始化的方式

C++提供了多种初始化成员变量的方式:

(1) 默认初始化

  • 如果没有显式初始化,成员变量会使用默认构造函数(如果有)或未定义的值。
  • 例如:
    class MyClass {int x; // 未显式初始化,值未定义
    };
    

(2) 成员初始化列表(Member Initializer List)

  • 在构造函数的初始化列表中显式初始化成员变量。
  • 这是推荐的方式,尤其是对于引用类型常量成员没有默认构造函数的类类型成员
  • 例如:
    class MyClass {
    public:int x;const int y;int& z;MyClass(int a, int b, int& c) : x(a), y(b), z(c) {} // 使用初始化列表
    };
    

(3) 构造函数体内赋值

  • 在构造函数体内对成员变量赋值。
  • 这种方式其实不是初始化,而是赋值操作。对于常量成员引用成员,详细的原因我在前面已经说明了,本质上就是因为二者一旦被初始化,对于常量成员值就不能被更改了,对于引用成员,与别的变量的绑定关系就不能再修改了。
  • 例如:
    class MyClass {
    public:int x;MyClass(int a) {x = a; // 赋值,不是初始化}
    };
    

(4) 默认成员初始化器(C++11 引入)

  • 在类定义中直接为成员变量提供默认值。
  • 例如:
    class MyClass {
    public:int x = 10; // 默认初始化
    };
    

3. 必须使用初始化列表的情况

以下成员变量必须在构造函数的初始化列表中初始化:

  • 常量成员(const:因为常量成员一旦初始化后就不能修改。
  • 引用成员:详细的原因见 https://blog.csdn.net/wenhao_ir/article/details/145422877
  • 没有默认构造函数的类类型成员:如果成员是一个类对象,且该类没有使用默认构造函数进行构造,则必须通过初始化列表显式初始化。

例如:

class MyClass {
public:const int x;int& y;MyClass(int a, int& b) : x(a), y(b) {} // 必须使用初始化列表
};

4. 初始化顺序

  • 成员变量的初始化顺序与它们在类中声明的顺序一致,而不是初始化列表中的顺序。
  • 例如:
    class MyClass {
    public:int x;int y;MyClass(int a) : y(a), x(y) {} // x 会先初始化,但 y 还未初始化,导致 x 的值未定义
    };
    

5. 总结

  • 所有成员变量必须在对象构造完成前初始化。
  • 初始化可以通过默认初始化成员初始化列表构造函数体内赋值默认成员初始化器实现,默认成员初始化器是C++11引入的。
  • 对于常量成员引用成员没有使用默认构造函数的类类型成员,必须使用成员初始化列表

http://www.ppmy.cn/devtools/155953.html

相关文章

马克思主义哲学知识梳理(考公版)

马克思主义哲学是照亮我们认识世界、改造世界的明灯,考公人学好它,笔试面试都能 “开挂”。下面就一起来梳理这些重要内容。 一、哲学 哲学就像是一门 “智慧的学问”,它是对世界基本和普遍的问题研究的学科,探索着宇宙、人生、…

记录一次,PyQT的报错,多线程Udp失效,使用工具如netstat来检查端口使用情况。

1.问题 报错Exception in thread Thread-1: Traceback (most recent call last): File "threading.py", line 932, in _bootstrap_inner File "threading.py", line 870, in run File "main.py", line 456, in udp_recv IndexError: list…

《AI大模型开发笔记》DeepSeek技术创新点

一、DeepSeek横空出世 DeepSeek V3 以颠覆性技术架构创新强势破局!革命性的上下文处理机制实现长文本推理成本断崖式下降,综合算力需求锐减90%,开启高效 AI 新纪元! 最新开源的 DeepSeek V3模型不仅以顶尖基准测试成绩比肩业界 …

深入理解SpringMVC:数据处理、文件上传与异常处理等常见技术应用及解决方案

目录 前言 第一章:数据处理与跳转 1. 结果跳转方式 2. 使用 ResponseBody 返回 JSON 数据 3. 配置静态资源不被拦截 第二章:SpringMVC 实现文件上传 1. 导入文件上传的依赖 2. 配置文件上传解析器 3. 文件上传示例 第三章:SpringMV…

小程序-模板与配置

前言 1. 数据绑定 定义数据 使用数据 然后我们把info渲染到页面上 1.1 绑定内容 这就是动态绑定内容 1.2 绑定属性 vue中绑定属性要用v,这个就不用了 绑定内容和属性都是Mustache语法 这样就不会变形了,因为宽度不变,高度变 1.3 三元运…

全面剖析 XXE 漏洞:从原理到修复

目录 前言 XXE 漏洞概念 漏洞原理 XML 介绍 XML 结构语言以及语法 XML 结构 XML 语法规则 XML 实体引用 漏洞存在原因 产生条件 经典案例介绍分析 XXE 漏洞修复方案 结语 前言 网络安全领域暗藏危机,各类漏洞威胁着系统与数据安全。XXE 漏洞虽不常见&a…

EF Core与ASP.NET Core的集成

目录 分层项目中EF Core的用法 数据库的配置 数据库迁移 步骤汇总 注意: 批量注册上下文 分层项目中EF Core的用法 创建一个.NET类库项目BooksEFCore,放实体等类。NuGet:Microsoft.EntityFrameworkCore.RelationalBooksEFCore中增加实…

在CentOS服务器上部署DeepSeek R1

在CentOS服务器上部署DeepSeek R1,并通过公网IP与其进行对话,可以按照以下步骤操作: 一、环境准备 系统要求: CentOS 8+(需支持AVX512指令集)。 硬件配置: GPU版本:NVIDIA驱动520+,CUDA 11.8+。 CPU版本:至少16核处理器,64GB内存。 存储空间:原始模型需要30GB,量…