【问题标题】:How can the synthesized default constructor initialize already initialized class members?合成的默认构造函数如何初始化已经初始化的类成员?
【发布时间】:2020-08-10 19:27:43
【问题描述】:

我正在学习类,C++ Primer 一书的第 7.1.4 章说:

编译器生成的构造函数被称为综合默认值 构造函数。对于大多数类,这个合成的构造函数 初始化类的每个数据成员如下:

  • 如果存在类内初始化程序(第 2.6.1 节,第 73 页),请使用它来初始化成员。
  • 否则,默认初始化(第 2.2.1 节,第 43 页)成员。

如果类成员已经有一个类内初始化器,为什么这个合成的默认构造器会再次初始化它们?另外,我认为初始化是一件只能发生一次的事情。以上建议成员被初始化两次,一次显式,一次由合成的默认构造函数隐式初始化。

【问题讨论】:

  • 它不会再次初始化它们。它使用类内初始化器来初始化类的成员变量。
  • 构造函数初始化所有成员数据。类内初始化器描述如何初始化成员,但它自己不做任何事情。构造函数使用它来初始化相应的成员。

标签: c++


【解决方案1】:

类中的初始化器实际上并不初始化任何东西。如果没有提供,它们都是使用此初始化程序的语法糖。所以,与

struct foo
{
    int a = 42;
    int b;
};

编译器会生成一个类似的构造函数

foo() : a(42)/*, b()*/ {}

因为a 有一个“初始化程序”而b 没有。注意b() 只是说明。因为bint,所以它没有初始化。

在更复杂的构造函数中,例如

struct foo
{
    int a = 42;
    int b;
    foo() : b(21) {}
};

由于类成员初始化列表中缺少a 成员,编译器会将a(42) 添加到列表中,因为这是要使用的默认初始化器。

如果你有

struct foo
{
    int a = 42;
    int b;
    foo() : a(3), b(21) {}
};

然后默认初始化器被忽略,a 的值将是3 而不是42

【讨论】:

  • 第一种情况更像foo() : a(42)/*, b()*/ {},因为bint,因为C++ 没有办法明确表达“不要初始化这个东西(我'以后会处理的,相信我)”。我希望 int b; 默认将其初始化为 0,而 int b = void; 将使其未初始化。唉。
【解决方案2】:

这里没有关于初始化成员的内容再次。 如果存在类内初始化程序,则合成的默认构造函数将使用它,这是该成员的第一次初始化。成员在调用构造函数之前不会被初始化,即使它们有类内初始化器。

您可以将类内初始化程序理解为编译器的指令,在没有为它提供其他初始化的情况下如何构建构造函数。

【讨论】:

    猜你喜欢
    • 2011-08-09
    • 1970-01-01
    • 1970-01-01
    • 2019-09-10
    • 1970-01-01
    • 1970-01-01
    • 2016-04-05
    • 2015-07-03
    • 2015-10-07
    相关资源
    最近更新 更多