After reading a lot of the questions regarding initialization of static variables I am still not sure how this applies to const
variables at namespace level.
I have kind of the following code in a header file config.h
generated by the build script:
static const std::string path1 = "/xyz/abc";
static const std::string path2 = "/etc";
According to what I have read the static
keyword is not necessary, even deprecated here.
My Question: Is the code above prone to the static initialization fiasco?
If I have the following in a header file myclass.h
:
class MyClass
{
public:
MyClass(const std::string& str) : m_str(str) {}
std::string Get() const { return m_str; }
private:
std::string m_str;
}
const MyClass myclass1("test");
Will this pose any problems with static initialization?
If I understood right, due to const
variables having internal linkage there should be no problem in both cases?
Edit: (due to dribeas answer)
Maybe I should mention that I am interested in use cases like:
In main.cpp
:
#include <config.h>
#include <myclass.h>
std::string anotherString(path1 + myclass1.Get());
int main()
{
...
}
Another question regarding this use case: Will the compiler optimize away path2
in this case?
Your first definition places
path1
in each compilation unit that includesconfig.h
. To avoid this, don't define variables in header files. Usually you'd declare the variables in the header asextern
:and define them in a translation unit, e.g.
config.cpp
:Sometimes you need a constant variable that is usable only from one translation unit. Then you can declare that variable at file scope as
static
.static
is not deprecated any more.static
andextern
are sometimes implied, but I always forget where and how, so I usually specify them explicitly for all namespace-level variables.Static initialization fiasco refers to static variables that depend on each other. Merely defining some
static const
variables will not be a source of problems.I tried to get the necessary information right from the C++03 Standard document. Here is what I found:
Regarding the
const static
declarations:According to section 3.5.3 objects defined at namespace level and declared
const
have internal linkage by default.static
also declares a namespace level object to have internal linkage so there is no need to declare an objectstatic const
.Also according to Annex D.2
Regarding the static initialization fiasco:
Since the variables are defined in a header file they are always defined before any other static objects using them.
From section 3.6.2.1:
Answer 1: This means passing the variables to a static object constuctor should be fine.
Answer 2: However a problem could occur if the variables are referenced from a non-inline constructor of a static object:
Neither in section 3.6.2.1 nor 3.6.2.3 is it specified in which order the static objects in different compilation units are initialized if dynamic initialization is done before the first statement of
main
.Consider the following:
Since
myclass.cpp
has its own copy of theconst
variables, these might not be initialized whenMyClass::MyClass()
is called.So yes,
const
variables defined in header files can be used in a way that is prone to the static initialization fiascoAs far as I can see this does only apply to variables not requiring static initialization:
From C++03 standard, section 3.6.2.1:
What is referred as the static initialization fiasco is a problem when one namespace level variable depends on the value assigned to a different namespace level variable that might or not be initialized before. In your two examples there is no such dependency and there should not be any problem.
This, on the other hand, is prone to that type of error:
There is no guarantee that
foo
will be initialized beforefoobar
, even if both are constant. That means that the program behavior is undefined and it could well print "foobar", "bar" or die.