1) If I'm not mistaken, C++ standard guarantees that static variables in a single translation unit are initialized in their definition order. And I'm confused about the following code fragment:
extern int n;
int k = n;
int n = 2;
extern int n;
is the declaration, not the definition, so k
is defined before n
, but GCC, Clang and MSVC all show me that k == 2
after the initialization of the global variables. For me it's unclear how can k
be assigned 2 after int k = n;
, because n
is not initialized at that point yet and its value must be zero.
If we change the last line to:
int n = func();
where func()
is non-constexpr, then k
will be assigned zero, as I expect. So, do initialization of the global variables at the compile time change the order of the initialization?
2) Here is another code fragment:
class Base
{
public:
struct static_constructor
{
static_constructor()
{
i = 1;
}
};
static static_constructor constructor;
static int i;
};
Base::static_constructor Base::constructor;
int Base::i = 2;
When Base::constructor
is defined, its constructor is called, and i = 1
assignment is performed. But at this point Base::i
is not defined yet, so, please, could you explain me what happens at this point and why is Base::i
equal to 1 in the end?
The first scenario is well-defined in [basic.start.init]/2:
(Emphasis mine)
The upshot of this fairly lengthy paragraph is that
is static initialization, while
is dynamic initialization (because
n
is not a constant expression), and thereforen
is initialized beforek
even if it appears later in the code.The same logic applies in the case of the
Base::static_constructor
example -- because the constructor ofBase::static_constructor
is notconstexpr
,Base::constructor
is dynamically initialized, whereasBase::i
is statically initialized. The initialization ofBase::i
therefore takes place before the initialization ofBase::constructor
.On the other hand, the second case with
puts you squarely in the territory of unspecified behavior, and it is quite explicitly mentioned in [basic.start.init]/3: