Конструктор для глобальных переменных выполняется до начала main, но порядок между единицами компиляции не указан.
Конструктор Foo
в вашем примере должен вызываться только после вызова Foo::Get
.Если вы в первый раз вызываете его в main
, статический вектор будет уже инициализирован.
Одна ситуация, в которой вы можете столкнуться с расой, которую вы описываете, - это когда вы вызываете Foo::Get
в инициализации.код другого глобального объекта, особенно когда код находится в другом модуле компиляции.
Но в таком простом тесте, как этот, здесь, вектор всегда должен сначала инициализироваться, и возможной гонки не будет:
class Foo {
Foo() = default;
public:
static Foo& Get() {
static Foo singleton;
return singleton;
}
static vector<int> s_vec;
};
vector<int> Foo::s_vec; // will be initialized before main
int main() {
Foo::Get(); // --> triggers constructor call Foo::Foo
return 0;
}
(я предполагаю, что Foo::Get
является статическим членом в синглтоне, иначе вы не сможете создать его экземпляр. Но это не имеет принципиального значения.)
Проблемный сценарий может выглядеть следующим образом:
// other file
struct Bar {
Bar() { Foo::Get(); }
};
Bar bar; // global object
Вы не можете управлять порядком инициализации Foo::s_vec
(в первом модуле компиляции) и bar
(во втором).