C++中构造函数的使用

Use of constructor in C++

本文关键字:构造函数 C++      更新时间:2023-10-16

关于C++中构造函数的使用,这是一个非常琐碎的问题。我将以采访对话的形式呈现(很难以任何其他形式呈现)

面试官-什么是构造函数
me-构造函数是特殊的函数,它确保所有对象在使用前都已初始化。

面试官-什么是初始值设定项列表
me-这是所有初始化发生的列表。只有在初始化了所有数据成员,或者调用了所有成员对象的某个构造函数之后,才能输入构造函数的主体。

interviewer-这意味着初始化是在初始化器列表中执行的,而不是在构造函数中执行的。但是你说构造函数初始化对象!你不是吗?你想回答我的第一个问题吗
me-我认为构造函数进行赋值,它在已经初始化的成员对象上调用赋值运算符。

所以我想问你的问题可以是

初始值设定项列表是如何工作的

函数的起始地址和;开始大括号[{]?

或者回答我如何说服面试官。

从技术上讲,您的解释是准确的。不能从ctor主体内部初始化任何成员;仅在CCD_ 2中。ctor主体中的任何成员访问都只能是分配。

在输入ctor正文之前,所有成员都已"初始化"。

然而,从广义上讲,由于主体总是遵循初始值设定项,因此据说—作为一个整体;一旦构造函数结束,就会初始化对象。。。包括身体。

部分原因是,从广义上讲,您可能会考虑初始化,以包括必须在ctor主体中执行的一些业务逻辑,尽管这与数据成员的实际初始化不同。

你想得太多了,让面试官把你弄糊涂了。

初始化对象的成员与初始化对象本身是一回事。仅仅因为成员具有合理的值并不意味着对象已经构造完成。在构造函数完成之前,对象本身尚未正确初始化。

初始化列表的主要内容是效率和代码可读性。

可读性部分是不言自明的,因为您确切地知道在哪里可以查看值的初始化位置。节省效率的原因是,如果你在构造函数的代码中为它们赋值,那么它们将被赋值两次:首先,当创建对象时,它们将被分配该数据类型的默认构造函数提供的值,然后,它们将在对象的构造函数中被分配一个新值。初始化列表只是确保它们是用您指定的值初始化的。

例如,这里有一个我在双链表实现中使用的初始化列表示例:

template <typename T>
LinkedList<T>::LinkedList()
: size(0)
, pHead(NULL)
, pTail(NULL)
{
}

而效率较低的版本,大小、pHead和pTail被分配两次,如下所示:

template <typename T>
LinkedList<T>::LinkedList()
{
    size = 0;
    pHead = NULL;
    pTail = NULL;
}

本质上,您是正确的,但成员初始值设定项不应被视为与构造函数分离。初始值设定项是构造函数的一部分,在构造函数的主体之前调用。

当您声明一个内置类型的自动变量时,它既是一个定义,也是一个声明。这是一个声明,因为标识符绑定到一个类型,它是一个定义,因为编译器为它分配存储

int var1; // declares/defines var of type int
int var2 = 0; // declares/defines a var of type int and initializes it to 0

初始值设定项在定义变量时为其设置初始值,但它被认为是在初始值设定器之前定义的。

int x = 5;
int y = 5;
int main()
{
    int x = x; // x is undefined here not 5 because x refers to itself
    int y[y];
    int size = sizeof(y)/sizeof(int); // size is 5 (y[5]) since y isn't defined until after the enclosing bracket so y referred to the global y in the declaration.
}

但是,必须初始化某些变量。常量和引用。

构造函数也是如此。定义成员的点就在ctor体之前。这是调用构造函数时定义成员和基的顺序。

  1. 虚拟基类
  2. 基类
  3. 成员——按照宣布的顺序
  4. 执行ctor主体

离开构造函数主体后,所有内容都已初始化。

如果不使用初始值设定项,那么在输入ctor主体时可以假设它已经定义好了,但不能假设它有任何特定的值。同样,常量和引用必须在成员初始值设定项中初始化。

初始化器列表是构造函数的一部分。每个构造函数都有自己的构造函数。