C++实现单例模式
提示:以下是本篇文章正文内容,下面案例可供参考
一、单例模式是什么?
无论怎么获取,永远只能得到该类类型的唯一一个实例对象。
注意下面三个点:
-
构造函数需私有化
将该类的构造函数私有化,目的是禁止其他程序创建该类的对象,同时也是为了提醒查看代码的人我这里是在使用单例模式,防止他人将这里任意修改。此时,需要提供一个可访问类自定义对象的类成员方法(对外提供该对象的访问方式)。 -
指向本身实例的类属性为静态
指向自己实例的私有引用在被类方法(Getinstance)调用时被初始化,只有静态成员变量才能在没有创建对象时进行初始化,并且类的静态成员在第一次使用时不会再被初始化,保证了单例,因此设置为静态。 -
通过一个static静态成员方法返回唯一的对象实例
通过类方法(GetInstance) 获取instance,类属性instance为静态的(static),则需要类的静态方法才能调用,因此该类方法应设为静态的。
二、程序
1.饿汉单例模式
饿汉式单例模式,顾名思义,就是程序启动时就实例化了该对象,并没有推迟到第一次使用该对象时再进行实例化;如果运行过程中没有使用到,该实例对象就被浪费掉了。
class CSingleton {
public:
static CSingleton* getInstance() {
return &single;
}
private:
static CSingleton single;
CSingleton();
~CSingleton();
CSingleton(const CSingleton&){}
};
CSingleton CSingleton::single;
2.懒汉单例模式
懒汉式单例模式,顾名思义,就是对象的实例化,延迟到第一次使用它的时候。
class CSingleton {
public:
static CSingleton* getInstance() {
if (single == nullptr) {
single = new CSingleton();
}
return single;
}
private:
static CSingleton* single;
CSingleton();
~CSingleton();
CSingleton(const CSingleton&){}
//注意如果没有下面的释放资源类,在main函数中将手动释放资源
class CRelease {
public:
~CRelease() { delete single; }
};
static CRelease release;
};
CSingleton* CSingleton::single = nullptr;
CSingleton::CRelease CSingleton::release;
3.线程安全单例模式
考虑在多线程下的情景
3.1 饿汉单例模式的线程安全特性
饿汉单例模式中,单例对象定义成了一个static静态对象,它是在程序启动时,main函数运行之前就初始化好的,因此不存在线程安全问题,可以放心的在多线程环境中使用。
3.2 饿汉单例模式的线程安全特性
getInstance是个不可重入函数,也就它在多线程环境中执行,会出现竞态条件问题。因此需要考虑加锁
class CSingleton
{
public:
static CSingleton* getInstance()
{
// 获取互斥锁
pthread_mutex_lock(&mutex);
if (nullptr == single)
{
single = new CSingleton();
}
// 释放互斥锁
pthread_mutex_unlock(&mutex);
return single;
}
private:
static CSingleton *single;
CSingleton()
~CSingleton()
{
pthread_mutex_destroy(&mutex); // 释放锁
}
CSingleton(const CSingleton&);
class CRelease
{
public:
~CRelease() { delete single; }
};
static CRelease release;
// 定义线程间的互斥锁
static pthread_mutex_t mutex;
};
CSingleton* CSingleton::single = nullptr;
CSingleton::CRelease CSingleton::release;
// 互斥锁的初始化
pthread_mutex_t CSingleton::mutex = PTHREAD_MUTEX_INITIALIZER;