关于c++中的两种单例模式
About two kinds of singleton pattern in C++
当我寻找有关c++的单例模式的信息时,我总是找到这样的例子:
class Singleton
{
public:
~Singleton() {
}
static Singleton* getInstance()
{
if(instance == NULL) {
instance = new Singleton();
}
return instance;
}
protected:
Singleton() {
}
private:
static Singleton* instance;
};
Singleton* Singleton::instance = NULL;
但是这种类型的单例似乎也同样有效:
class Singleton
{
public:
~Singleton() {
}
static Singleton* getInstance()
{
return &instance;
}
protected:
Singleton() {
}
private:
static Singleton instance;
};
Singleton Singleton::instance;
我猜第二个单例是在程序开始时实例化的,不像第一个,但这是唯一的区别吗?
为什么我们主要发现前者?
http://www.parashift.com/c + + -faq-lite/ctors.html #常见问题- 10.14
静态初始化顺序失败是一个非常微妙和常见的问题c++中被误解的方面。不幸的是它很难被发现错误通常发生在main()开始之前。简而言之,假设您有两个静态对象x和y,它们存在于分离源文件,例如x.p和y.p。进一步假设y对象的初始化(通常是y对象的构造函数)调用x对象上的某个方法。
就是这样。就这么简单。
悲剧的是你有50%-50%的机会死亡。如果x.cpp的编译单元恰好首先被初始化好。但是如果y.cpp的编译单元先初始化,那么y的初始化会在x的初始化之前运行你在烤面包。例如,y的构造函数可以调用x的方法对象,但是x对象还没有被构造。
您列出的第一个方法完全避免了这个问题。它被称为"首次使用时构造习惯用法"
这种方法的缺点是对象永远不会被析构。还有另一种技术可以解决这个问题,但它需要要小心使用,因为它创造了另一个(同样)的可能性令人讨厌的问题。
注意:在某些情况下,静态初始化顺序失败也可能导致适用于内置/内在类型。
第一个允许您删除实例,而第二个不允许。但是请注意,你的第一个例子不是线程安全的
这通常被称为static
初始化顺序惨败。总之,文件范围内的静态实例不必在显式函数调用之前初始化,如第一个示例所示。
单例模式通常被认为是坏实践,因此经验证据(您"看到最多"的东西)在这种情况下几乎没有价值。
第一个版本使用动态分配,第二个版本使用静态分配。也就是说,第二次分配不能失败,而第一次分配可能会抛出异常。
第一个也是"lazy" -它只在需要时才会被创建。如果您的Singleton
是昂贵的,这可能是您想要的。
如果你的Singleton
是便宜的和你可以处理未定义的静态初始化顺序(你不使用它之前main()),你不妨去第二个解决方案
- C++单例模式代码无法运行,不知道为什么?
- 工厂模式和单例模式:未定义的引用
- 使用静态和避免单例模式声明全局变量
- 如何在 c++ 中使用单例模式时编写 cmake 文件
- 可派生类的单例模式
- 这是单例模式的正确实现吗?
- 懒惰的初始化使用单例模式
- 带参数的单例模式对象
- 另一个类上使用的单例模式
- 这是单例模式的示例吗?
- 了解单例模式中的操作重载
- 为什么我们在C++的单例模式中使用静态方法和静态函数
- 强制单例模式的静态函数
- 当周围有线程时,创建类的许多实例会失败吗?- 单例模式
- 为什么这种单例模式不起作用?
- 这种c++单例模式和方法公开是一种好的实践吗?
- c++单例模式_实现和内存管理
- 单例模式实现错误
- c++日志器的单例模式
- 关于c++中的两种单例模式