I have the following program:
#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;
}
Here foo
's constructor is not a constant expression, so we'll have dynamic initialization of foo
. But bar
's constructor seems to be a constant expression, so we'll have static initialization of bar
. So, bar
's ctor must be called before foo
's one and we'll see 1
as output. And I observe such result for GCC 8.3.0 and Clang 8.0.0. But for Visual C++ actual output is 0
and when I debug the application, I see that foo
's dynamic initialization is made first and then bar
's dynamic initialization is made.
Is the behavior that I observe (bar.value == 0
) valid according to C++ 17 standard?
I'm using C++ compiler version 19.16.27027.1 for x86 Debug build or Release build with ctor's marked with __declspec(noinline)
.
Probably I am late to the party, but this is a compiler bug, which also affects some portions of Boost,see https://developercommunity.visualstudio.com/t/class-with-constexpr-constructor-not-using-static/336946
This bug was fixed in: visual studio 2019 version 16.5 (March, 2020).
BTW, C++20 introduces the keyword constinit
to assert that a variable has static initialization.