Global const initializing and difference between constructor in .h or .cpp file
I was wondering why sometimes my global const defined in seperate .h file isn't properly initialized when I need it. Some tests lead me to situation that I can't understand. I don't know how to explain it, so here's the code:
main.cpp
#include <iostream>
#include "class.h"
using namespace std;
A a;
B b;
int main(int argc, char* argv[]){
A aa;
B bb;
cout<<a.a<<" "<<aa.a<<endl;
cout<<b.b<<" "<<bb.b<<endl;
return 0;
}
class.h
#ifndef CLASS_H
#define CLASS_H
#include "const.h"
class A {
public:
A();
float a;
};
class B {
public:
B():b(CONST){}
float b;
};
#endif
class.cpp
#include "class.h"
A::A()
: a(CONST){}
const.h
#ifndef CONST_H
#define CONST_H
#include <limits>
using namespace std;
const float CONST = numeric_limits<float>::has_infinity ?
-numeric_limits<float>::infinity() :
-numeric_limits<float>::max();
#endif
After running above code I get:
0 -1.#INF
-1.#INF -1.#INF
when actually I would like to get 4 times '-1.#INF'. Why does it happen this way? If CONST would be '1' instead of above formula, it would work perfectly.
I can "fix" it by making static getConst() method:
static float getConst(){
static const float CONST = numeric_limits<float>::has_infinity ?
-numeric_limits<float>::infinity() :
-numeric_limits<float>::max();
return CONST;}
b开发者_运维百科ut it just doesn't "feel" right. On other hand I just need two of those above... But maybe there's some other way?
And, most importantly, why class B gets "right" CONST and class A don't?
The order of initialization of global object in different translation unit is not guarantee.
Please have a look at this stackoverflow question: Static variables initialisation order
Constant objects have internal linkage, so you get a separate copy of CONST
in each compilation unit that includes const.h
. In this case, you'll get one in main.cpp
, and one in class.cpp
. You also have your two global objects in main.cpp
.
C++ does not define the order in which global objects in different compilation units are initialised. A
s constructor is called from main.cpp
, and needs the global constant from class.cpp
, which may not yet be initialised. In your particular case, it hasn't been, so you get the incorrect value you saw. B
s constructor is inline, so it uses the global constant from main.cpp
, which has been initialised since it is defined earlier in the same compilation unit.
By making the constant a function-static object, it is now guaranteed to be initialised when that function is first called.
I don't see the contents of const.h
anywhere so I can only guess what CONST
is (a macro?).
That aside, in your code example, the member variable A::a
is not initialized. Hence, it could have any value - it's uninitialized.
If I'm understanding your question properly then I believe the problem is because the order of initialisation of any global objects is not defined.
精彩评论