在声明或实现中延迟初始化C ++单例

时间:2017-07-12 09:25:26

标签: c++ design-patterns singleton

我知道单身模式通常被认为是一种糟糕的设计,因此不鼓励,但这个问题涉及实施方面,而不是单身模式的适当性。

使用延迟初始化考虑C ++中单例的以下三种实现:

1:使用指针,在声明和实现之间进行划分

Singleton.hpp:

T001

Singleton.cpp:

class Singleton {
public:
   static Singleton* instance();
private:
   Singleton() {}
   static Singleton* singleton;
};

2:使用引用,在声明和实现之间划分

Singleton.hpp:

Singleton* Singleton::singleton = nullptr;

Singleton* Singleton::instance() {
    if( nullptr == singleton ) {
        singleton = new Singleton();
    }
    return singleton;
}

Singleton.cpp:

class Singleton {
public:
   static Singleton& instance();
private:
   Singleton() {}
};

3:使用引用,内联声明

Singleton.hpp:

Singleton& Singleton::instance() {
    static Singleton singleton;
    return singleton;
}

我个人喜欢并使用第三个版本。但是,有没有什么好理由更喜欢第一版或第二版?

据我所知,在第三个版本中,每个翻译单元都有一个对象实例,其中包含class Singleton { public: static Singleton& instance() { static Singleton singleton; return singleton; } private: Singleton() {} } ,然后链接器选择一个。这会导致任何副作用吗?

在共享库中使用第三个有副作用吗?

奖金问题:哪些实施实际上是"迈耶的单身"?

1 个答案:

答案 0 :(得分:1)

第一个是线程安全。

 if( nullptr == singleton ) {
    singleton = new Singleton();
}

多个线程可能会执行分配语句并创建内存泄漏

第二个和第三个是自C ++ 11 以来的线程安全,因为:

  

如果多个线程尝试初始化相同的静态本地   并发变量,初始化恰好发生一次(类似   使用std :: call_once可以获得任意函数的行为。

来自here

我更喜欢第三种,因为内联优化更有可能。