单例模式
1、概念:单例模式是指在整个系统生命周期内,保证一个类只能产生一个实例,确保该类的唯一性。
2、实现思路:
(1)私有化该类的构造函数和析构函数,以防止外界创建单例类的对象。
(2)拷贝构造函数和赋值构造函数为私有或者删除,目的是禁止外部拷贝和赋值,确保实例的唯一性。
(3)使用类的私有静态指针变量指向该类的唯一实例
(4)通过一个公有静态方法获取该实例
3、实现方式:
(1)懒汉模式:在第一次使用该对象时进行初始化
(2)饿汉模式:在程序运行时立即初始化
4、代码
(1)懒汉模式(不安全)
#include <memory>
#include <mutex>
using namespace std;
class SingleInstance
{
public:
SingleInstance(SingleInstance&) = delete;
SingleInstance& operator=(const SingleInstance&) = delete;
static SingleInstance* getInstance()
{
/*
这里使用了两个 if 判断语句的技术称为双检锁;
好处是,只有判断指针为空的时候才加锁。
*/
if (ptr_ == nullptr)
{
lock_guard<mutex> locker(mutex_);
if (ptr_ == nullptr)
{
ptr_ = new SingleInstance();
}
}
return ptr_;
}
private:
~SingleInstance() { cout << "~SingleInstance() delete" << endl; }
SingleInstance() { cout << "SingleInstance() create" << endl; }
static SingleInstance* ptr_;
static mutex mutex_;
};
SingleInstance* SingleInstance::ptr_ = nullptr;
mutex SingleInstance::mutex_;
每次调用 GetInstance的方法都加锁,但是锁的开销是比较大的。因此采用另一种实现方式。
(2)静态局部变量的懒汉单例(线程安全)
// 双检测锁模式不够优雅,C++11编译器保证函数内的局部静态对象的线程安全性。
class SingleInstance
{
private:
//禁止外部构造
SingleInstance() {}
//禁止外部析构
~SingleInstance() {}
// 禁止外部拷贝构造
SingleInstance(const SingleInstance &signal);
// 禁止外部赋值操作
const SingleInstance &operator=(const SingleInstance &signal);
public:
static SingleInstance* getinstance();
};
SingleInstance* SingleInstance::getinstance()
{
/**
* 局部静态特性的方式实现单实例。
* 静态局部变量只在当前函数内有效,其他函数无法访问。
* 静态局部变量只在第一次被调用的时候初始化,也存储在静态存储区,生命周期从第一次被初始化起至程序结束止。
*/
static SingleInstance obj;
return &obj;
}
(3)饿汉模式(线程安全)
// 在程序运行时就定义并对其初始化,故不需要锁就可以实现线程安全。
class SingleInstance {
private:
SingleInstance() {}
~SingleInstance() {}
// 禁止外部拷贝构造
SingleInstance(const SingleInstance &signal);
// 禁止外部赋值操作
const SingleInstance &operator=(const SingleInstance &signal);
// 唯一单实例对象指针
static SingleInstance* p;
public:
static SingleInstance* getinstance();
};
SingleInstance* SingleInstance::p = new SingleInstance();
SingleInstance* SingleInstance::getinstance() {
return p;
}