我有以下程序:
#include <iostream>
void Init();
struct Foo {
Foo() {
int *p = new int; // just to make sure Foo's ctor is not a constant expression
Init();
}
} foo;
struct Bar {
constexpr Bar()
: value(0) { }
int value;
} bar;
void Init() {
bar.value = 1;
}
int main()
{
std::cout << bar.value << std::endl;
}
这里foo
的构造函数不是常量表达式,因此我们将对foo
进行动态初始化。但是bar
的构造函数似乎是一个常量表达式,所以我们将对bar
进行静态初始化。因此,必须在bar
之前调用foo
的ctor,我们将看到1
作为输出。我观察到GCC 8.3.0和Clang 8.0.0的结果。但是对于Visual C ++,实际输出是0
,当我调试应用程序时,我看到foo
的动态初始化首先进行,然后进行bar
的动态初始化。
根据C ++ 17标准,我观察到的行为(bar.value == 0
)是否有效?
我正在使用C ++编译器版本19.16.27027.1进行x86调试构建或发布构建,其中ctor标记为__declspec(noinline)
。
但是
bar
的构造函数似乎是一个常量表达式,所以我们将对bar
进行静态初始化。
这是一个错误的理解。
constexpr
构造函数也可用于构造非const
对象。发生这种情况时,将使用动态初始化初始化该对象。在你的情况下,bar
是一个非const
对象。因此,使用动态初始化初始化它是有意义的。
将代码更改为:
struct Bar {
constexpr Bar()
: value(0) { }
int value;
};
constexpr Bar bar;
应该将bar
的初始化更改为静态初始化。
但是,如果将bar
更改为const
对象,则无法使用
bar.value = 1;
在Init()
。我只是想指出如何更改bar
,以便在静态初始化期间初始化它。