C++对象模型(一):The Semantics of Constructors The Default Constructor (默认构造函数什么时候会被创建出来)

简介:

本文是 Inside The C++ Object Model, Chapter 2的部分读书笔记。

C++ Annotated Reference Manual中明确告诉我们: default constructor会在需要的时候被编译器产生出来。注意,这里是编译器需要,而不是程序需要。后来的C++ Standard 95修改了这种说法,但是实质上仍是相同的: For class X, if there is none user declared constrator, one default constructor will be implicitly generated by the Compiler.

但实际上,如果default constructor是trivial(无用的),那么编译器根本就不会产生它!只有一下四种情况,non-trivial default constructor会被产生出来,来保证C++语言的机制能够按照预期工作:

  1)带有Default Constructor的Member Class Object

      如果该class X 包含有带有默认构造函数的成员class object (member object),那么编译器需要对此class X合成一个default constructor。不过该合成只在该合成操作真正被调用时。

     被合成的这个default constructor,包含有调用这个member class的default constructor的代码,但是它不会初始化它自身其他的成员变量,比如char *str; int data;这些成员变量的初始化时设计者的责任,而不是编译器的职责!

   由此有进一步的思考,如果是设计者已经定义了constructor,来初始化比如char *str; int data; 那么编译器如何初始化其他的member class object呢? 答案就是编译器需要扩张该class的constructor,以按照member class object的声明顺序来调用各个class的default constructor。


2) 带有Default Constructor的Base Class

    如果class X继承自一个带有default constructor的class, 那么编译器将为这个class生成non-trivial的default constructor,并且按照base class的顺序逐次调用。

   如果user declared 许多constructors,但是没有default constructor(就是没有任何参数的那个constructor),那么编译器不会产生default constructor了。而是扩张每个constructor,使其包含必要的default constructor的扩张代码,比如初始化它的member class object。 参考第一种情况


3) 带有virtual function

     对于有virtual function的class,一个virtual function table会被编译器产生出来,存着virtual functions的地址。 而在每一个class的object中,会有一个pointer member(称为vptr)会被编译器生成出来,内容那个class virtual function table的地址。

   所以编译器为了使得virtual function的机制生效,必须要为每个这种class的object生成合理的vptr,而vptr的赋值就发上在扩张后的constructors里。如果class没有任何的constructors,那么default constructor会被认为是non-trivial并且会被生成。如果class有constructor/s,那么所有的constructor都会扩张以赋予vptr以合理的值。


4)带有一个virtual base class的class

    Virtual base class的实现在不同 的编译器间有极大的差异。共同点就是virtual base class 在其每一个derived class object的位置,在执行期间能够准备妥当。这些工作都要放到constructor中去完成。


总结
  在合成的default constructor中,只有base class subobjects 和member class objects才会初始化。所有其他的nonstatic data member,都不会被初始化,这些工作应该由设计者(程序猿)而不是编译器去完成。

目录
相关文章
|
编译器 C++ 开发者
【C++篇】深度解析类与对象(下)
在上一篇博客中,我们学习了C++的基础类与对象概念,包括类的定义、对象的使用和构造函数的作用。在这一篇,我们将深入探讨C++类的一些重要特性,如构造函数的高级用法、类型转换、static成员、友元、内部类、匿名对象,以及对象拷贝优化等。这些内容可以帮助你更好地理解和应用面向对象编程的核心理念,提升代码的健壮性、灵活性和可维护性。
|
编译器 C语言 C++
类和对象的简述(c++篇)
类和对象的简述(c++篇)
|
12月前
|
编译器 C++
类和对象(中 )C++
本文详细讲解了C++中的默认成员函数,包括构造函数、析构函数、拷贝构造函数、赋值运算符重载和取地址运算符重载等内容。重点分析了各函数的特点、使用场景及相互关系,如构造函数的主要任务是初始化对象,而非创建空间;析构函数用于清理资源;拷贝构造与赋值运算符的区别在于前者用于创建新对象,后者用于已存在的对象赋值。同时,文章还探讨了运算符重载的规则及其应用场景,并通过实例加深理解。最后强调,若类中存在资源管理,需显式定义拷贝构造和赋值运算符以避免浅拷贝问题。
|
12月前
|
存储 编译器 C++
类和对象(上)(C++)
本篇内容主要讲解了C++中类的相关知识,包括类的定义、实例化及this指针的作用。详细说明了类的定义格式、成员函数默认为inline、访问限定符(public、protected、private)的使用规则,以及class与struct的区别。同时分析了类实例化的概念,对象大小的计算规则和内存对齐原则。最后介绍了this指针的工作机制,解释了成员函数如何通过隐含的this指针区分不同对象的数据。这些知识点帮助我们更好地理解C++中类的封装性和对象的实现原理。
|
C++ 芯片
【C++面向对象——类与对象】Computer类(头歌实践教学平台习题)【合集】
声明一个简单的Computer类,含有数据成员芯片(cpu)、内存(ram)、光驱(cdrom)等等,以及两个公有成员函数run、stop。只能在类的内部访问。这是一种数据隐藏的机制,用于保护类的数据不被外部随意修改。根据提示,在右侧编辑器补充代码,平台会对你编写的代码进行测试。成员可以在派生类(继承该类的子类)中访问。成员,在类的外部不能直接访问。可以在类的外部直接访问。为了完成本关任务,你需要掌握。
302 19
|
12月前
|
编译器 C++
类和对象(下)C++
本内容主要讲解C++中的初始化列表、类型转换、静态成员、友元、内部类、匿名对象及对象拷贝时的编译器优化。初始化列表用于成员变量定义初始化,尤其对引用、const及无默认构造函数的类类型变量至关重要。类型转换中,`explicit`可禁用隐式转换。静态成员属类而非对象,受访问限定符约束。内部类是独立类,可增强封装性。匿名对象生命周期短,常用于临时场景。编译器会优化对象拷贝以提高效率。最后,鼓励大家通过重复练习提升技能!
|
存储 编译器 数据安全/隐私保护
【C++面向对象——类与对象】CPU类(头歌实践教学平台习题)【合集】
声明一个CPU类,包含等级(rank)、频率(frequency)、电压(voltage)等属性,以及两个公有成员函数run、stop。根据提示,在右侧编辑器补充代码,平台会对你编写的代码进行测试。​ 相关知识 类的声明和使用。 类的声明和对象的声明。 构造函数和析构函数的执行。 一、类的声明和使用 1.类的声明基础 在C++中,类是创建对象的蓝图。类的声明定义了类的成员,包括数据成员(变量)和成员函数(方法)。一个简单的类声明示例如下: classMyClass{ public: int
495 13
|
安全 编译器 C语言
【C++篇】深度解析类与对象(中)
在上一篇博客中,我们学习了C++类与对象的基础内容。这一次,我们将深入探讨C++类的关键特性,包括构造函数、析构函数、拷贝构造函数、赋值运算符重载、以及取地址运算符的重载。这些内容是理解面向对象编程的关键,也帮助我们更好地掌握C++内存管理的细节和编码的高级技巧。
|
存储 程序员 C语言
【C++篇】深度解析类与对象(上)
在C++中,类和对象是面向对象编程的基础组成部分。通过类,程序员可以对现实世界的实体进行模拟和抽象。类的基本概念包括成员变量、成员函数、访问控制等。本篇博客将介绍C++类与对象的基础知识,为后续学习打下良好的基础。
|
机器学习/深度学习 人工智能 自然语言处理
C++构建 GAN 模型:生成器与判别器平衡训练的关键秘籍
生成对抗网络(GAN)是AI领域的明星,尤其在C++中构建时,平衡生成器与判别器的训练尤为关键。本文探讨了GAN的基本架构、训练原理及平衡训练的重要性,提出了包括合理初始化、精心设计损失函数、动态调整学习率、引入正则化技术和监测训练过程在内的五大策略,旨在确保GAN模型在C++环境下的高效、稳定训练,以生成高质量的结果,推动AI技术的发展。
419 10