现在就单例模式的几种实现方式进行比较:
1、最常见的单例写法
使用static私有变量,并提供一个静态方法作为单例的接口。让构造成为私有的,即该对象不能通过类外进行实例化。
class Singleton
{
public:
void myInfo();
static Singleton * getInstance();
private:
Singleton();
~Singleton();
static Singleton * m_sglton ;//(此处也可直接写为静态变量)
};
Singleton* Singleton:: m_sglton = NULL;//初始化在主线程之前
Singleton *Singleton::getInstance()
{
if(m_sglton == NULL)
{
m_sglton = new Singleton;
}
return sglton;
(返回对象)}
优点:简单易于理解,缺点容易忘记释放内存。
2、静态局部变量的写法
- 返回了静态局部对象的指针
不用担心内存释放的问题,
class Singleton
{
public:
void myInfo();
static Singleton * getInstance();
private
Singleton();
~Singleton();
:
};
Singleton *Singleton::getInstance()
{
static Singleton siglton;
return &siglton;
}
- 返回静态局对象的引用,由于担心发生该对象的拷贝,将其拷贝构造和赋值构造改为私有函数。
class Singleton
{
public:
void myInfo();
static Singleton &getInstance();
private:
Singleton();
~Singleton();
Singleton(const Singleton &);
Singleton &operator =(const Singleton &);
};
Singleton &Singleton::getInstance()
{
static Singleton siglton;
return siglton;
}
Singleton test = Singleton::geInstance();这种情况出现时,编译报错。
线程安全问题:
当使用静态局部变量,在多线程时,会出现线程安全问题,即线程重入。而静态成员变量的写法因为在main函数执行之前就已经进行了初始化,所以不必考虑线程安全问题。
- 对静态局部变量采取线程安全的写法(加锁)
class Singleton
{
public:
void myInfo();
static Singleton &getInstance();
private:
Singleton();
~Singleton();
Singleton(const Singleton &);
Singleton &operator =(const Singleton &);
};
Singleton &Singleton::getInstance()
{
Lock();
static Singleton siglton;
UnLock();
return siglton;
}
发现问题
细心的读者可能发现了一个问题,我在使用单例模式的时候,在其静态成员函数中实例化了一个对象,该对象的私有构造函数得到执行(非静态成员函数执行)。这与静态函数不能调用类的非静态成员规则矛盾吗?
下一篇《静态成员函数与私有构造函数与》将会对这块内容进行探索!