I am returning to C++ after a long absence and I am stumbling a little over my understanding of the fairly well known static initialization problem.
Let’s say I have a simple class Vector2 as given below (note that I am aware that x and y should be private with getters and setters, these have just been omitted for brevity):
class Vector2 {
public:
Vector2(float x, float y) :x(x), y(y) {};
float x,y;
}
Now, if I want to specify a static const member to represent a Vector2 with x and y set to 1, I am unsure on how to proceed – will static const members fall foul of the static initialization problem or will the act of making them const mean they are ok? I am toying with the following possibilities:
Possibility 1:
// .h
class Vector2 {
public:
Vector2(float x, float y) :x(x), y(y) {}
static const Vector2 ONE;
float x,y;
};
// .cpp
const Vector2 Vector2::ONE = Vector2(1.f, 1.f);
Possibility 2:
// .h
class Vector2 {
public:
Vector2(float x, float y) :x(x), y(y) {}
static const Vector2& getOne();
float x,y;
private:
static const Vector2 ONE;
};
// .cpp
const Vector2 Vector2::ONE = Vector2(1.f, 1.f);
static const Vector2& Vector2::getOne() {
return ONE;
}
Possibility 3:
// .h
class Vector2 {
public:
Vector2(float x, float y) :x(x), y(y) {}
static const Vector2& getOne();
float x,y;
};
// .cpp
const Vector2& Vector2::getOne() {
static Vector2 one(1.f,1.f);
return one;
}
Now, my preferred way to write this would be as in possibility 2, just because it is a more comfortable syntax for me. However, if I call the getOne() method from another static method in another class am I going to risk crashing and burning? As I say, it is because I am using a static const rather than a plain static that I am asking this question as I have found much on plain static class member issues, but nothing on const static issues.
I suspect that I gain nothing by the fact that I am using static const and will need to go with Possibility 3 to be safe, but I just want to ask in case someone can shed some light on this for me.
I realise I am probably opening myself up to a slew of links pointing to exactly what I am asking, but I have looked and not found before posting this.
Any help will be gratefully appreciated.
All of them, except possibility
3, suffer from the static initialization order fiasco. This is because your class is not a POD. In C++0x, this problem can be solved by marking the constructorconstexpr, but in C++03 there is no such solution.You can remove the constructor to solve the problem in C++03, and initialize using
This is initializing a POD, and all initializers in the list are constant expression (for the purpose of static initialization). The intialization of them happen before any code is run that might access it before being initialized.
3.6.2:8.5.1/14: