C++ 有效的单例类?;
这是有效的单例类吗C++ 有效的单例类?;,c++,design-patterns,singleton,C++,Design Patterns,Singleton,这是有效的单例类吗 class Singleton { private: static Singleton s; Singleton(){} public: static Singleton *getInstance() { return &s; } }; Singleton Singleton::s; 上面的三个单例类都是线程安全的,但它们都容易出现“静态初始化顺序失败”,对吗 这是有效的单例类吗 class Sin
class Singleton
{
private:
static Singleton s;
Singleton(){}
public:
static Singleton *getInstance()
{
return &s;
}
};
Singleton Singleton::s;
上面的三个单例类都是线程安全的,但它们都容易出现“静态初始化顺序失败”,对吗 这是有效的单例类吗
class Singleton
{
private:
static Singleton s;
Singleton(){}
public:
static Singleton *getInstance()
{
return &s;
}
};
Singleton Singleton::s;
现在,在编辑之后,答案是肯定的,它是有效的&它也是线程安全的,因为所有非函数作用域静态变量都是在main()
之前构造的,而只有一个活动线程
C++标准n3337§3.6.2/1§3.6.2/2:非局部变量的初始化
有两大类命名的非局部变量:具有
静态存储持续时间(3.7.1)和线程存储持续时间
(3.7.2). 具有静态存储持续时间的非局部变量为
由于程序启动而初始化。非本地
具有线程存储持续时间的变量初始化为
线程执行的结果。在初始化的每个阶段中,初始化如下所示
具有静态存储持续时间(3.7.1)或线程存储的变量
持续时间(3.7.2)应在任何其他时间之前初始化为零(8.5)
初始化发生。执行常量初始化:
-如果每个完整表达式(包括隐式转换)
出现在带有static或thread的引用的初始值设定项中
存储持续时间是一个常量表达式(5.19),引用为
绑定到指定具有静态存储持续时间的对象的左值
或临时(见12.2)
-如果初始化了具有静态或线程存储持续时间的对象
通过构造函数调用,如果构造函数是constexpr构造函数,
如果所有构造函数参数都是常量表达式(包括
转换),如果在函数调用替换(7.1.5)之后,
mem初始值设定项中的每个构造函数调用和完整表达式,以及
在大括号或相等值中,非静态数据成员的初始值设定项是
恒定表达
-如果不支持具有静态或线程存储持续时间的对象
由构造函数调用初始化,如果
出现在其初始值设定项中的是一个常量表达式
零初始化和常量初始化一起被称为
静态初始化;所有其他初始化都是动态的
初始化。静态初始化应在任何
进行动态初始化。(……)
C++标准n3337§6.7/4:声明声明
所有具有静态变量的块范围变量的零初始化(8.5)
存储持续时间(3.7.1)或线程存储持续时间(3.7.2)为
在进行任何其他初始化之前执行。常数
使用静态存储初始化块范围实体(3.6.2)
持续时间(如果适用)在第一次执行其块之前执行
进入。允许实现提前执行
使用静态或线程初始化其他块作用域变量
与实施相同条件下的存储持续时间
允许使用static或thread静态初始化变量
命名空间范围中的存储持续时间。否则,这样的变量是
控件第一次通过其声明时初始化;
这样一个变量被认为是在它的操作完成时初始化的
初始化。如果初始化通过引发异常退出,
初始化未完成,因此将在下一次重试
时间控件进入声明如果控件输入声明
在初始化变量时,并发
执行应等待初始化完成*)。(…)
*):
实现不能在执行时引入任何死锁
初始化器
但它仍然很容易受到影响。编写getInstance
的常用方法是:
class Singleton
{
private:
static Singleton *m_instance;
Singleton(){}
public:
static Singleton *getInstance()
{
if(m_instance == NULL)
{
lock();
if(m_instance == NULL)
m_instance = new Singleton;
unlock();
}
return m_instance;
}
};
Singleton * Singleton::m_instance = NULL;
这样可以避免这个初始化问题
这是线程安全的单例类吗
class Singleton
{
private:
static Singleton s;
Singleton(){}
public:
static Singleton *getInstance()
{
return &s;
}
};
Singleton Singleton::s;
在C++11中,上述代码是线程安全的。在C++03中,可以使用
除此之外,还应防止复制和分配:
Singleton& getInstance()
{
static Singleton instance;
return instance;
}
据我所知,它是线程安全的。但它很容易受到影响 如果一个对象试图访问其构造函数中的
Singleton
,并且该对象是在程序初始化期间构造的,并且该代码位于Singleton
之外的另一个编译单元中,则它可能会崩溃,也可能不会崩溃,因为Singleton::s
可能尚未初始化(因为编译单元之间静态对象的初始化顺序未定义)。以下是一个示例:
Singleton( Singleton const&); // Don't Implement
void operator=( Singleton const&); // Don't implement
这是懒惰的初始化Singleton,是的,它是线程安全的C++ 11。< /P>你能举个例子吗?@利泽克,我增加了一个例子。初始化的顺序问题是C++中使用单体的主要原因之一。“这是懒惰的初始化Singleton,是的……不,不是!在C++ 11之前,对象初始化可能是D。一对多线程上面的三个单例类都是线程安全的,但它们都容易“静态初始化顺序失败”,对吗?@Lizusekt它们在C++11(而不是C++03)中都是线程安全的,但在静态初始化顺序失败的情况下更容易发生@lizusek!