概述
对类的实例化只进行一次,即运行内存中只加载一次该类,需要该类向外提供唯一的访问接口。嵌入式Qt开发中软键盘的类以及通用的日期时间组件等需要用到该模式。
关键点
单例类有且仅有一个实例
单例类必须自行创建自己的唯一实例
单例类必须给所有其它对象提供这一实例
应用
1.局部静态变量方式
singClass.h文件中:
#ifndef SINGCLASS_H
#define SINGCLASS_H
/*实现 */
//提供一个private构造函数(防止外部调用而构造类的实例)
//提供一个该类的static private对象
//提供一个static public 函数,用于创建或获取其本身的静态私有对象(getInstance())
//线程安全问题,资源释放问题
//局部静态变量资源自动释放
class singClass
{
public:
//向外提供唯一的实例化
static singClass* getInstance(){
static singClass instance;
return &instance;
}
//验证测试成功函数,可替换为业务函数
int sum(int a,int b){
return a+b;
}
private:
singClass(){}//构造函数私有化防止外部调用
};
#endif // SINGCLASS_H
实际调用时:
#include <iostream>
#include "singclass.h"
using namespace std;
int main()
{
singClass* test=singClass::getInstance();
int c=test->sum(2,7);
cout << "return value is:" <<c;
return 0;
}
2.懒汉方式
singClass.h文件中:
#ifndef SINGCLASS_H
#define SINGCLASS_H
#include <iostream>
#include <mutex>
using namespace std;
/*单例-懒汉(双检锁DCL机制)方式实现 */
//第一次调用时才初始化,避免内存浪费
//需要加锁才能保证线程安全,但加锁会影响效率
//资源释放,一般采用程序自动释放,更加方便
class singClass
{
public:
//向外提供唯一的实例化
static singClass* getInstance(){
if(m_instance == nullptr)
{
std::lock_guard<std::mutex> lock(m_mutex);//自解锁
if(m_instance == nullptr){
m_instance=new singClass();
}
}
return m_instance;
}
//验证测试成功函数,可替换为业务函数
int sum(int a,int b){
return a+b;
}
//程序自动去释放资源
class CG{
public:
~CG(){
//可以在这里释放需要释放的资源
if(nullptr != m_instance){
cout << "delete m_instance"<<endl;
delete m_instance;
m_instance=nullptr;
}
}
private:
static CG cg;
};
private:
singClass(){}//构造函数私有化防止外部调用
static singClass *m_instance;
static mutex m_mutex;
};
singClass * singClass::m_instance=nullptr;//重要
singClass::CG singClass::CG::cg;
mutex singClass::m_mutex;
#endif // SINGCLASS_H
实际调用同方式1
结果如下图所示
控制台执行结果图
3.饿汉方式
singClass.h文件中:
#ifndef SINGCLASS_H
#define SINGCLASS_H
#include <iostream>
using namespace std;
/*单例-饿汉方式实现 */
//类加载时就初始化,浪费内存
//多线程安全,不需要加锁,执行效率会提高
//资源释放,一般采用程序自动释放,更加方便
class singClass
{
public:
//向外提供唯一的实例化
static singClass* getInstance(){
return m_instance;
}
//验证测试成功函数,可替换为业务函数
int sum(int a,int b){
return a+b;
}
//程序自动去释放资源
class CG{
public:
~CG(){
//可以在这里释放需要释放的资源
if(nullptr != m_instance){
cout << "delete m_instance"<<endl;
delete m_instance;
m_instance=nullptr;
}
}
private:
static CG cg;
};
private:
singClass(){}//构造函数私有化防止外部调用
static singClass *m_instance;
};
singClass * singClass::m_instance=new singClass();//重要
singClass::CG singClass::CG::cg;
#endif // SINGCLASS_H
实际调用同方式1