这里是否保证静态初始化?

4

看看这段代码:

struct Foo {
        void *ptr;

        constexpr Foo() : ptr(nullptr) { }
};

Foo f;

保证f会静态初始化吗?

在这里,Clang使用静态初始化,但MSVC不使用


1
我认为Clang会进行优化,因为它检测到构造函数对内存进行了零初始化。我不认为这种优化是必需的,因为它只适用于简单的情况。 - Phil1970
3个回答

3
是的,标准规定f将被常量初始化:
[basic.start.init] / 2:
常量初始化是指对象o的常量表达式初始化,但它也可以调用o及其子对象的constexpr构造函数,即使这些对象是非字面类类型[注意:这样的类可能具有非平凡的析构函数--end note]。进行常量初始化的情况包括:
- ... [对于引用的情况] - 如果一个具有静态存储期或线程存储期的对象通过构造函数调用进行初始化,并且如果初始化完整表达式是该对象的常量初始化程序; - ... [对于不需要构造函数调用进行初始化的对象的情况]
零初始化和常量初始化一起称为静态初始化;所有其他初始化都是动态初始化。必须在进行任何动态初始化之前执行静态初始化。
初始化完整表达式只是调用Foo的默认构造函数,这是一个常量表达式。
MSVC发出初始化f的代码是错误的。

0

从标准的角度来看,是的。但从现实情况来看,则不然。

在涉及静态初始化遵从性时,你要完全依赖于编译器供应商的恩惠。

[编辑] Clang 是一款特殊的编译器 - 从一开始,它的创作者就一直关注着完整的标准遵从性。


那篇文章似乎误用了“静态初始化”这个术语来谈论“动态初始化”。“静态初始化顺序混乱”(也是一个令人困惑的名称)只会在两个初始化程序都使用动态初始化时发生。 - aschepler
嗯...你说得对。我的脑子有点僵了。我会从我的答案中删除它。 - Dúthomhas

0

我相信如果你将f本身声明为constexpr Foo f;,它也会在msvc(至少vs 2015)中出现。


除了这会不必要地阻止您在程序中修改 f 以外。 - aschepler
当然。根据你的目标,这可能是可以的或不可以的。 - zen-cat

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接