【发布时间】:2017-07-12 09:25:25
【问题描述】:
我知道单例模式通常被认为是一种糟糕的设计,因此不鼓励使用,但这个问题涉及实现方面,而不是单例模式的适当性。
考虑以下三种使用延迟初始化的 C++ 单例实现:
1:使用指针,分离声明和实现
单例.hpp:
class Singleton {
public:
static Singleton* instance();
private:
Singleton() {}
static Singleton* singleton;
};
单例.cpp:
Singleton* Singleton::singleton = nullptr;
Singleton* Singleton::instance() {
if( nullptr == singleton ) {
singleton = new Singleton();
}
return singleton;
}
2:使用引用,拆分声明和实现
单例.hpp:
class Singleton {
public:
static Singleton& instance();
private:
Singleton() {}
};
单例.cpp:
Singleton& Singleton::instance() {
static Singleton singleton;
return singleton;
}
3:使用引用,在声明中内联
单例.hpp:
class Singleton {
public:
static Singleton& instance() {
static Singleton singleton;
return singleton;
}
private:
Singleton() {}
}
我个人喜欢并使用第三个版本。但是有什么好的理由更喜欢第一个或第二个版本吗?
据我了解,在第三个版本中,每个翻译单元都有一个包含Singleton.hpp 的对象实例,然后链接器选择一个。这会导致任何副作用吗?
在共享库中使用第三个有什么副作用吗?
额外问题:哪个实现实际上是“Meyer 的单例”?
【问题讨论】:
-
井引用不能为空,所以不能使用第二种和第三种方法进行惰性实例化
-
@spug 带有初始化的局部静态变量将在第一次调用函数时被初始化。
-
第二个选项(Meyers Singleton)保证在 C++11 中是线程安全的,你知道吗。
-
@StoryTeller 第二个版本也应该是线程安全的。它们之间的唯一区别是,在第二种选择中,
instance函数不能被内联。实例的初始化仍然是线程安全的。 -
@VTT - “没有显式控制”,这就是懒惰评估的重点......
标签: c++ design-patterns singleton