Do I need to worry about the static initialization order fiasco when using a static data member as a default argument value? For example:
class Thing {
static double const default_blarg; // initialized in another file
void run(double blarg=default_blarg);
};
I know default_blarg
will be initialized at a mostly-unspecified point at link time, but I'm not sure when the default argument to run
is initialized. If it's at some point that could be before default_blarg
is initialized, what approach could I use to safely expose the default value as part of the class interface without repeating it? Would using constexpr
for the static data member make it safe?
Note that I'm aware that this could yield some very confusing behavior if default_blarg
wasn't const (that's why it is), and I'm not trying to use a non-static data member.
You still have to be worried about the static initialization order fiasco. Lets say you have a.cpp and b.cpp. In a.cpp you have
Now in a.cpp any call to
run
after this point will have a initialized default and you are good to go. Unfortunately in b.cpp you have another static object that happens to create an instance ofThing
and callrun
.Now we do not know what will happen. If b.cpp runs first then
default_blarg
is not initialized and we have undefined behavior.Now for you second part
The default arguments of a function are evaluated each time the function is called. So as long as the function is called after
default_blarg
is initialized(and as noted above it may not) you will be okay.From the C++11 Standard, Section 8.3.6/9:
As long as
Thing::default_blarg
is initialized beforeThing::run
is called, you should see predictable behavior.