0

所以假设我正在使用这个玩具示例:

struct Foo {
    int member;
};

我知道默认构造函数不会默认初始化member。因此,如果我这样做,member仍然未初始化:const Foo implicit_construction. 顺便说一句,这似乎工作正常:const Foo value_initialization = Foo()尽管我的理解是这实际上并没有使用默认构造函数。

如果我Foo这样改变:

struct Foo {
    Foo() = default;
    int member;
};

我尝试这样做const Foo defaulted_construction,不出所料,它的行为implicit_constructionmember未初始化完全一样。

最后,如果我改成Foo这样:

struct Foo {
    Foo(){};
    int member;
};

我这样做:const Foo defined_construction member 零初始化的。我只是想弄清楚隐式定义的构造函数是什么样的。我本来会的Foo(){}。不是这样吗?是否还有其他一些黑魔法在起作用,使我定义的构造函数的行为与默认构造函数不同?


编辑:

也许我在这里被误导了。defaulted_construction肯定是未初始化的。
虽然defined_construction肯定是初始化的。

我认为这是标准化的行为,这是不正确的吗?

4

1 回答 1

3

您所遇到的称为默认初始化,其规则是(强调我的):

  • 如果 T 是非 POD(C++11 前)类类型,则考虑构造函数并对其进行针对空参数列表的重载决议。调用选择的构造函数(默认构造函数之一)为新对象提供初始值;
  • 如果 T 是数组类型,则数组的每个元素都是默认初始化的;
  • 否则,什么都不做:具有自动存储持续时间的对象(及其子对象)被初始化为不确定的值。

编辑,以响应以下OP的请求:

请注意,声明构造函数= default不会改变这种情况(再次强调我的):

隐式定义的默认构造函数

如果隐式声明的默认构造函数没有定义为deleted,如果odr-used是由编译器定义(即生成并编译一个函数体),与用户自定义构造函数的效果完全相同空主体和空初始化列表。也就是说,它调用这个类的基类和非静态成员的默认构造函数。

由于默认构造函数有一个空的初始化列表,它的成员满足默认初始化的条件

默认初始化在三种情况下执行:

...

3) 当构造函数初始化器列表中未提及基类或非静态数据成员并且调用该构造函数时。

另请注意,在通过实验确认这一点时必须小心,因为 an 的默认初始化值完全有int可能为零。特别是,您提到了这一点:

struct Foo {
    Foo(){};
    int member;
} foo;

结果value-initialization,但没有;在这里,member是默认初始化的。

编辑2:

请注意以下区别:

struct Foo {
    int member;
};

Foo a; // is not value-initialized; value of `member` is undefined
Foo b = Foo(); // IS value-initialized; value of `member` is 0

这种行为可以通过遵循value-initialization的规则来理解:

在以下情况下执行值初始化:

1,5) 当使用由一对空括号组成的初始化器创建无名临时对象时;

表格 1 ( T();) 是上面右侧=用于初始化的表格b

值初始化的效果是:

1) 如果 T 是一个没有默认构造函数或用户提供或删除的默认构造函数的类类型,则该对象是默认初始化的;

2) 如果 T 是一个类类型,其默认构造函数既不是用户提供也不是被删除(也就是说,它可能是一个具有隐式定义或默认的默认构造函数的类),则该对象被零初始化,然后它是如果它具有非平凡的默认构造函数,则默认初始化;

3) 如果 T 是数组类型,则数组的每个元素都是值初始化的;

4) 否则,对象被零初始化。

最后,请注意在我们之前的示例中:

struct Foo {
    Foo(){}; // this satisfies condition (1) above
    int member;
};

Foo f = Foo();

现在,条件(1)适用,我们的(空)用户声明的构造函数被调用。由于此构造函数未初始化membermember因此是默认初始化的(因此其初始值未定义)。

于 2018-05-30T16:14:51.620 回答