单例模式
- 实现了单例(Singleton)模式的类在整个程序运行期间只能生成一个实例对象
- 单例模式分为懒汉式和饿汉式两种,所谓懒汉式是指需要使用实例对象时才开始创建,而饿汉式是指在需要使用实例对象之前进行创建
- 实现单例模式需要的条件:
(1)将类的构造函数的访问权限设为私有
(2)将类的拷贝构造函数、赋值运算符均设为私有
(3)定义一个指向类的唯一实例对象的静态指针,将其设为私有,并提供公有接口(必须为静态)
饿汉模式
class Singleton
{
private:
static Singleton* m_singleton;
Singleton() {} //构造函数设为私有
//将拷贝构造函数和赋值运算符均设为私有
Singleton(const Singleton&);
Singleton& operator=(const Singleton&);
// 由于单例模式是在堆上生成的,因此程序结束后会自动释放(所以感觉CG类不需要)
class CG
{
public:
~CG()
{
if (m_singleton)
delete m_singleton;
m_singleton = nullptr;
}
};
static CG cg;
public:
static Singleton* GetSingleton();
};
Singleton* Singleton::m_singleton = new Singleton; //类内可以调用构造函数
Singleton* Singleton::GetSingleton()
{
return m_singleton;
}
Singleton::CG Singleton::cg;
class Singleton
{
private:
Singleton(){}
Singleton(const Singleton &);
Singleton & operator=(const Singleton &);
static Singleton m_singleton;
public:
static Singleton * GetSingleton();
};
Singleton Singleton::m_singleton;
Singleton * Singleton::GetSingleton()
{
return &m_singleton;
}
- 饿汉式是在初始化静态变量
m_singleton时进行创建的,因此,程序运行时能够确保只创建一个实例对象同时可以工作在多线程环境下
- 饿汉式不是在调用
GetSingleton才创建的,而是在初始化阶段就已经被创建了,过早的创建实例可能会引起内存使用率下降
懒汉式
#include <mutex>
class Singleton
{
private:
Singleton() {}
Singleton(const Singleton&);
Singleton& operator=(const Singleton&);
static Singleton* m_singleton;
static mutex i_mutex; //互斥锁
public:
static Singleton* GetSingleton()
{
if (m_singleton == nullptr)
{
i_mutex.lock();
if (m_singleton == nullptr)
{
m_singleton = new Singleton();
}
i_mutex.unlock();
}
return m_singleton;
}
};
Singleton* Singleton::m_singleton = nullptr; //类中的static变量必须在类外初始化
mutex Singleton::i_mutex;
class Singleton
{
private:
Singleton() {}
Singleton(const Singleton&);
Singleton& operator=(const Singleton&);
public:
static Singleton* GetSingleton()
{
static Singleton m_singleton;
return &m_singleton;
}
};
- 系统在对静态变量进行初始化时会自动加锁,使静态变量的初始化成为线程安全的
- 懒汉模式使用时才进行创建,因此内存利用率较好,但创建过程需要进行加锁解锁操作,效率不如饿汉模式
参考文献
- C++单例模式(饿汉式)
- C++设计模式之单例模式详解(懒汉模式、饿汉模式、双重锁)
- 设计模式——单例模式(饿汉、懒汉、线程安全)||c++详解