【发布时间】:2016-02-01 01:38:47
【问题描述】:
如果具有静态存储持续时间的对象的 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段中,默认初始化的相关案例是:
...不执行初始化
我读到的意思是默认初始化不会更改先前的零初始化。
我是否遗漏了一些在构造函数调用开始时将所有成员重置为“不确定值”的其他文本?
我在 stackoverflow 上发现了有关零初始化和 默认初始化,但我看不到任何 分析了默认初始化之后会发生什么 同一实体的一些早期初始化。
在这种情况下,可能没有实际效果。但是在一个更复杂的构造函数中,一些成员初始化而其他成员没有,编译器是否必须准确跟踪哪些字节/位被初始化?或者它可以只初始化整个对象(例如,将构造函数简化为 memset() 调用)?
【问题讨论】:
-
我删除了我的答案,因为我不确定:
Foo是一个具有非平凡初始化的对象,这意味着它的生命周期只有在其构造函数完成后才开始。那么,我不确定其成员的价值观。在构造函数开始执行之前,您甚至可能无法访问它们(通过规范规则),所以我很难知道它们在那个时候存储了值(零)......更不用说第一个对象的存在了地点。 -
@LightnessRacesinOrbit re“嗯,不,如果它只是在草案中,那么它不在标准中,不应该被依赖”..那么我们很难编写大多数真实世界的代码,我认为.鉴于有多少缺陷报告(一些仍处于打开状态)试图修复标准中的错误 :) 例如,open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#191
-
@ᐅJohannesSchaub-litbᐊ 实际上,我认为您删除的答案是一个很好的答案。如果在构造函数调用之前静态存储持续时间对象完全不存在,我很难理解零初始化。例如,编译器在后台将“object”替换为由“new Foo()”初始化的隐藏指针是否有效?
-
@Johannes:我同意;真是一团糟!
-
@user1998586 我更倾向于这没关系。 12.6.2p6 还说如果成员未初始化,则该值是不确定的。但它并没有说没有被构造函数初始化。零初始化也很重要,所以这些不会冲突,IMO。
标签: c++ constructor language-lawyer storage-duration