如果具有静态存储期的对象的C++构造函数未初始化成员,是否需要保留先前的零初始化,还是将成员留有不确定值?
我对C++规范的理解是,它自相矛盾。
示例:
#include <iostream>
struct Foo { Foo(); int x; } object;
Foo::Foo() { }
int main() { std::cout << object.x << std::endl; }
Foo() 构造函数没有显式初始化成员对象x,因此根据12.6.2第8段中的注释:
“该成员具有不确定值。”
但是通过详细分析各种初始化的细节,这似乎是不正确的。member对象x由于具有静态存储期,因此进行了零初始化,然后我看不到任何改变它的方法。
关于构造函数,在12.6.2中适用的文本为:
“实体是默认初始化的。”
在8.5第7段中,默认初始化的相关情况是:
“...不执行任何初始化。”
我认为这意味着先前的零初始化不会被默认初始化更改。
我是否漏掉了重置所有成员在构造函数调用开始时返回"不确定值"的其他文本?
我在stackoverflow上找到了一些关于零初始化和默认初始化的其他问题,但我找不到任何分析当默认初始化跟随同一实体的早期初始化时会发生什么的问题。
在这种情况下,可能没有实际影响。但在更复杂的构造函数中,有些成员已初始化而其他成员没有,编译器是否必须精确跟踪初始化的字节/位?还是可以只初始化整个对象(例如,将构造函数简化为memset()调用)?
Foo
是一个具有非平凡初始化的对象,这意味着只有在其构造函数完成后才开始其生命周期。我不确定其成员变量的值。在构造函数开始执行之前,您甚至可能无法访问它们(按规范规则),所以我很难相信它们已经有初值(零)存储了..更别提首次存在对象。 - Johannes Schaub - litbS *p = malloc(sizeof*p); p->a = 1; new (p) S; /* p现在引用一个不同的新对象 */ int x = p->a;
但这是无效的:S *p = malloc(sizeof*p); int *pa = &p->a; *p = 1; new (p) S; /* p现在引用一个不同的对象,但pa已经失效并且没有被重新设置 */ int x = *pa; /* UB */
。但请记住:我不是专家,我说的一切都可能是错的!规范中并不是非常清楚... - Johannes Schaub - litb