首页 > 解决方案 > Static Initialization Order for Singletons

问题描述

So I'm reading that for Zero Initialization will initialize:

Every named variable with static or thread-local storage duration that is not subject to constant initialization, before any other initialization

I am using a Singleton with the traditional private constructor and a static public method in which there is a local static singleton object which the method will be return.

My problem is that the class also has a static vector which is zero-initialized and it seems to be getting initialized after the singleton, meaning that I cannot interact with it. Is there something that governs this initialization order or is that simply implementation defined?


This is a simplification of what my code looks like:

class Foo {
    Foo(){ s_vec.push_back(13); }
public:
    static Foo& Get() {
        static Foo singleton;
        return singleton;
    }

    int Front() const { return s_vec.front(); }
    static vector<int> s_vec;
};
vector<int> Foo::s_vec;

I'm running into this problem because elsewhere in the code I'm initializing a static global variable like this and not getting 13: static const auto element = Foo.Get().Front()

标签: c++staticsingletonstatic-variableszero-initialization

解决方案


全局变量的构造函数在 main 开始之前执行,但未指定跨编译单元的顺序。

您示例中的Foo构造函数只应在您调用Foo::Get. 如果您第一次调用它是 in 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(在第二个编译单元中)的初始化顺序。


推荐阅读