The eThe C++ Standard, [stmt.dcl], paragraph 4 [ISO/IEC 14882-2014], states:
...
In this noncompliant code example, the value of numWheels num_wheels in file1.cpp relies on c being initialized. However, because c is defined in a different translation unit (file2.cpp) than numWheels num_wheels, there is no guarantee that c will be initialized by calling get_default_car() before numWheels num_wheels is initialized by calling c.get_num_wheels(). This is often referred to as the "static initialization order fiasco", and the resulting behavior is unspecified.
| Code Block | ||||
|---|---|---|---|---|
| ||||
// file.h
#ifndef FILE_H
#define FILE_H
class Car {
int numWheelsnum_wheels;
public:
Car() : numWheelsnum_wheels(4) {}
explicit Car(int numWheelsnum_wheels) : numWheels(numWheelsnum_wheels(num_wheels) {}
int get_num_wheels() const { return numWheelsnum_wheels; }
};
#endif // FILE_H
// file1.cpp
#include "file.h"
#include <iostream>
extern Car c;
int numWheelsnum_wheels = c.get_num_wheels();
int main() {
std::cout << numWheelsnum_wheels << std::endl;
}
// file2.cpp
#include "file.h"
Car get_default_car() { return Car(6); }
Car c = get_default_car(); |
...
This compliant solution uses the "construct on first use" idiom to resolve the static initialization order issue. Because the numWheels num_wheels object was moved into the body of a function, its initialization is guaranteed to happen when control flows over the point of declaration, ensuring control over the order. The global object c is initialized before execution of main() begins, so by the time get_num_wheels() is called, c is guaranteed to have already been dynamically initialized.
| Code Block | ||||
|---|---|---|---|---|
| ||||
// file.h
#ifndef FILE_H
#define FILE_H
class Car {
int numWheelsnum_wheels;
public:
Car() : numWheelsnum_wheels(4) {}
explicit Car(int numWheelsnum_wheels) : numWheels(numWheelsnum_wheels(num_wheels) {}
int get_num_wheels() const { return numWheelsnum_wheels; }
};
#endif // FILE_H
// file1.cpp
#include "file.h"
#include <iostream>
int &get_num_wheels() {
extern Car c;
static int numWheelsnum_wheels = c.get_num_wheels();
return numWheelsnum_wheels;
}
int main() {
std::cout << get_num_wheels() << std::endl;
}
// file2.cpp
#include "file.h"
Car get_default_car() { return Car(6); }
Car c = get_default_car(); |
...