C ++默认初始化是否保留先前的零初始化?

时间:2015-10-31 20:17:15

标签: c++ constructor language-lawyer storage-duration

如果具有静态存储持续时间的对象的C ++构造函数没有初始化成员,那么是否需要保留先前的零初始化,或者是否使成员具有不确定的值?

我对C ++规范的解读是它与自身相矛盾。

示例:

#include <iostream>

struct Foo { Foo(); int x; } object;

Foo::Foo() { }

int main() { std::cout << object.x << std::endl; }

Foo()构造函数没有显式初始化成员object.x,所以 根据12.6.2第8段的说明:

  

该成员具有不确定的价值。

但是,通过各种初始化的细节,这似乎是 不对。成员object.x由于具有静态存储持续时间而被零初始化,然后我看不到任何改变它的内容。

关于构造函数,12.6.2中适用的文本是:

  

该实体是默认初始化的。

在第8.5段第7段中,默认初始化的相关案例是:

  

...没有执行初始化

我读到这意味着默认初始化不会改变先前的零初始化。

我是否遗漏了一些其他文字,将所有成员重置为&#34;不确定价值&#34;在构造函数调用的开头?

我在stackoverflow上找到了关于零初始化的各种其他问题 默认初始化,但我看不到任何 分析了默认初始化之后会发生什么 一些早期初始化同一个实体。

在这种情况下,可能没有实际效果。但是在一个更复杂的构造函数中,一些成员被初始化而其他成员没有,编译器是否必须准确地跟踪哪些字节/位被初始化?或者它是否只是初始化整个对象(例如,将构造函数简化为memset()调用) )?

1 个答案:

答案 0 :(得分:3)

Defect report 1787导致N3914中记录的更改为applied to the draft standard for C++14。哪个改变[dcl.init]第12段来自:

  

如果没有为对象指定初始化程序,则该对象为   默认初始化;如果没有执行初始化,则使用一个对象   自动或动态存储持续时间具有不确定的值。 [ 注意:   具有静态或线程存储持续时间的对象是零初始化的,   见3.6.2。 - 结束说明]

为:

  

如果没有为对象指定初始化程序,则该对象为   默认初始化。 使用自动或自动存储对象时   获得动态存储持续时间,该对象具有不确定性   值,如果没有为对象执行初始化,那么   对象保留不确定的值,直到该值被替换为   (5.17 [expr.ass])。 [注意:具有静态或线程存储的对象   持续时间为零初始化,见3.6.2 [basic.start.init]。 -结束   注意]如果评估产生了不确定的值,那么   除以下情况外,行为未定义:

     

[...]

这清楚地表明,对于自动或动态存储持续时间的对象,仅发生不确定值情况。由于这是通过缺陷报告应用的,它可能也适用于C ++ 11,因为缺陷报告在C ++ 14被接受之前发生,但它也可以进一步应用。我不清楚缺陷应该适用多远的规则。

由于在评论中提出了新的贴图,同样的更改也修改了 [expr.new] 部分,使得不确定的值部分成为评论:

  

如果省略new-initializer,则默认初始化该对象   (8.5 [dcl.init]);如果。 [注意:如果没有执行初始化,则   对象具有不确定的值。 - 后注]

该部分的开头说:

  

[...]由new-expression创建的实体具有动态存储   持续时间(3.7.4)。[...]

这似乎足以应用 [dcl.init] 部分中的更改。

此更改也很有趣,因为在此更改C ++标准中的术语indeterminate value was not defined之前。