The title is a bit of a mouthful, so let me explain.
Static data includes:
- The namespace domain variable √ defined in namespace
- The class domain variable √ declared static in a class
- A local static variable × declared static in a function
- The global variable defined in the file (with or without the static modifier) √
Non-local static data mentioned above refers to cases 1, 2, and 4 in addition to case 3.
O files. If a project consists of n individual CPPS and corresponding header files, it will be pre-compiled to generate n. O files, sometimes we call these *.
In summary, the implication of the title of this article is that if multiple static data (without local variables) are defined separately in multiple files, their interdependencies can be tricky.
What’s the dilemma? The thing is, since static data is initialized (either by default or automatically) at the start of the program, and the C++ standard does not specify the initialization order of these static data in multiple files, there is a problem: If the non-local static data are interdependent, the results of the program will be unpredictable due to the uncertainty of the initialization order.
For example, programmer Jack has developed a super useful class called Car and defined an object of this class to be used by others.
Class car // Non-open source code
{
. .
public :
void startup(params);
. .
};
extern car BMW; // A high-performance car ^__^
On the other hand, at different times and different places, different programmers Rose developed a logistics MF based on different purposes, naturally using Jack’s car object to complete some work.
class MF
{
public:
MF(params);
. .
};
MF::MF(params)
{
. .
BMW.startup(); // Use the car object
}
Soon Rose’s code would have disastrous consequences because the C++ compiler could not guarantee that the BMW car object would be initialized when the MF object was initialized. Therefore, it is very likely that MF called the startup function of an uninitialized object, which is embarrassing.
It is easy to avoid this by defining a function that handles the non-local static data in these troublesome multi-compiled units. Such as:
car &BMW() { static car c; // local static object c return c; }
At this point, Rose’s use of the CAR object requires only one small change:
MF::MF(params)
{
. .
BMW().startup(); // Use the car object
}
That’s right, a pair of parentheses after BMW. When Rose first calls BMW, the local static object C is created and initialized. This ensures that the startup() function is called correctly. Second, if startup() has not been called once, Then the local static object C will not be generated at all! Perfect!
Through this design, we solve two problems at the same time: the order of initialization is guaranteed, and the performance of the program is improved.