Reputation: 3369
For example:
#include<iostream>
using namespace std;
class A
{
public:
A(){cout<<k<<endl;}//make some output
static int k;
};
A a;//before `k`'s definition
int A::k=666;
int main()
{
}
Is the answer guaranteed to be 666
(I've tested it in gcc8.1.0 the answer is 666
) or causing undefined behavior?
What's more, in this example, object a
and definition A::k
are in the same translation unit, what will happen if they are in different units, since
Initialization of static variables in different translation units is indeterminately sequenced
From my point of view, since in the same TU the initializaition order is fixed, the answer of the example above should be undfined.
Upvotes: 5
Views: 285
Reputation: 1766
Static
member is given a separate room. Whether you initialize it before object creation of the class or not, will not have any effect. The program will run without undefined
behavior.
For example In C#, the if the static
member's value is not set, it is given 0
value by the compiler.
static
member after the object creation of the
classAfter setting it as 666
, other objects made of that class A
will get it value as 666
Upvotes: 0
Reputation: 170193
If you were to make the constructor a non-inline function, yes, it would be guaranteed to be the value you expect.
k
will be subject to constant initialization (on account of the constant initializer), while a
's initialization is dynamic. All static initialization happens before dynamic initialization of static objects. But even if k
was initialized dynamically:
[basic.start.dynamic] (emphasis mine)
4 It is implementation-defined whether the dynamic initialization of a non-local non-inline variable with static storage duration is sequenced before the first statement of main or is deferred. If it is deferred, it strongly happens before any non-initialization odr-use of any non-inline function or non-inline variable defined in the same translation unit as the variable to be initialized. It is implementation-defined in which threads and at which points in the program such deferred dynamic initialization occurs.
And a non-inline constructor qualifies for such a function. This is the basis for the Schwarz Counter technique.
But in your example, the c'tor is an inline function. So it's only due to constant initialization that you get 666. Should the initializer not be a constant expression, a
would be undergo dynamic initialization before k
according to declaration order in the same TU.
Upvotes: 4
Reputation: 238441
Are static data members initialized before all class objects?
Depends. All objects with static storage duration, which includes all static data members, are initialised before main
. But if you have class objects with static storage duration, then those class objects may be initialised before static data members.
Is the answer guaranteed to be 666
Yes.
causing undefined behavior?
No UB here.
what will happen if they are in different units
Initialisation of the static member is constant, while the constructor of a
is called during the dynamic initialisation of static objects. Constant initialisation phase is before dynamic phase. Thus it doesn't matter in this case whether they are declared in different TU's.
Upvotes: 2