The "Effective C + +" clause 4 mentions "notice the initialization order of non-static variables in different compilation units"
The following description is very detailed, reproduced here.
http://blog.csdn.net/chgaowei/article/details/6001433
The static object includes the global object, the object defined in the namespace scope, the object within class, the object within the function, and the objects declared as static within the file scope.
A Local-static object refers to an object defined inside a function. The others are called non-local-static objects.
A compilation unit is the code that produces a single target file, usually a source program and a header file that it is an include.
Questions :
There are two classes of definitions:
class Test1
{
Public:
Test1 ()
{
printf ("Test1 constructor./n");
T2.test ();
}
Virtual
~test1 ( )
{
printf ("Test1 destructor./n");
}
void Test ()
{
printf ("Test1 test function/n");
}
};
class Test2
{
Public:
Test2 ()
{
printf ("Test2 constructor./n");
}
Virtual
~test2 ( )
{
printf ("Test2 destructor./n");
}
void Test ()
{
printf ("Test2 test function/n");
}
};
int Main ()
{
printf ("Hello world!/n");
return 1;
}
Two source files: The test1.c,test2.c has two definitions, respectively:
Test1 T1;
Test2 T2;
The test environment is Linux AS5.0,GCC. The compilation order in the Makefile file is: test2.c, test1.c
T1 and T2 are non-local static variables, and their construction is done before the main function.
Compile and execute, print as:
Test1 the constructor function.
Test2 test function
Test2 the constructor function.
Hello world!
Test2 the destructor.
Test1 test function
From the above printing can be seen:
1, T1, and T2 are non-local static variables, and their construction is done before the main function.
2, T1 and T2 are constructed in the same order as they were compiled in makefile.
3. Destructors are performed when the main function exits. And the destructor sequence is the opposite of the construction order.
4. Because the non-local static variable T2 is called in the T1 constructor, T2 is not constructed at this time. may cause serious consequences.
To avoid access before object construction, you can change the compilation order of the compilation units in makefile to resolve them.
In addition, there is a better way:
Move each non-local static object into its own exclusive function that returns a pointer to the object's reference and no longer accesses the object directly.
Test1 *GetT1()
{
Static Test1 T1;
return &t1;
}
Test2 *GetT2()
{
Static Test2 T2;
return &t2;
}
At the same time, the Test1 constructor is changed to:
Test1 ()
{
printf ("Test1 constructor./n");
Gett2->test ();
}
In this way, you can ensure that T2 has been constructed, regardless of the order of the compilation units in the Makefile, when you access T2 T1 construction:
Test1 the constructor function.
Test2 the constructor function.
Test2 test function
Hello world!
Test2 the destructor.
Test1 test function
In addition, this method can reduce the number of global variables, so that the use of variables can be monitored.
Note: T1 and T2 can also be defined as static, but this may be a bit of a hassle when referencing T2.
Goto: Initialization Order of non-local static objects defined in different compilation units