我知道单身模式通常被认为是一种糟糕的设计,因此不鼓励,但这个问题涉及实施方面,而不是单身模式的适当性。
使用延迟初始化考虑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() {}
}
,然后链接器选择一个。这会导致任何副作用吗?
在共享库中使用第三个有副作用吗?
奖金问题:哪些实施实际上是"迈耶的单身"?
答案 0 :(得分:1)
第一个是不线程安全。
if( nullptr == singleton ) {
singleton = new Singleton();
}
多个线程可能会执行分配语句并创建内存泄漏。
第二个和第三个是自C ++ 11 以来的线程安全,因为:
如果多个线程尝试初始化相同的静态本地 并发变量,初始化恰好发生一次(类似 使用std :: call_once可以获得任意函数的行为。
来自here。
我更喜欢第三种,因为内联优化更有可能。