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 object static const
.
Also according to Annex D.2
The use of the static keyword is
deprecated when declaring objects in
namespace scope (see 3.3.5).
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:
Objects with static storage duration
defined in namespace scope in the same
translation unit and dynamically
initialized shall be initialized in
the order in which their definition
appears in the translation unit.
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:
// consts.h
#include <string>
const std::string string1 = "ham";
const std::string string2 = "cheese";
// myclass.h
#include <string>
class MyClass
{
public:
MyClass();
MyClass(std::string str);
std::string Get() { return memberString; }
private:
std::string memberString;
}
// myclass.cpp
#include "consts.h"
#include "myclass.h"
MyClass::MyClass() : memberString(string1) {}
MyClass::MyClass(std::string str) : memberString(str) {}
// main.cpp
#include <iostream>
#include "consts.h"
#include "myclass.h"
MyClass myObject1;
MyClass myObject2(string2);
using namespace std;
int main()
{
cout << myObject1.Get(); // might not print "ham"
cout << myObject2.Get(); // will always print "cheese"
}
Since myclass.cpp
has its own copy of the const
variables, these might not be initialized when MyClass::MyClass()
is called.
So yes, const
variables defined in header files can be used in a way that is prone to the static initialization fiasco
As far as I can see this does only apply to variables not requiring static initialization:
From C++03 standard, section 3.6.2.1:
Objects of POD types (3.9) with static
storage duration initialized with
constant expressions (5.19) shall be
initialized before any dynamic
initialization takes place.