C++单例模式
单例类,顾名思义就是类对象实例唯一,不会被重复多次构造。
划重点
1、构造函数私有化,防止外部调用构造类的实例;
2、提供一个静态私有对象,用于访问自身;
3、提供一个 static public 函数,用于创建或获取其本身的静态私有对象;
4、涉及到多线程时,线程安全问题;
5、资源释放。
懒汉式 and 饿汉式
懒汉式
// singleton.h
#ifndef SINGLETON_H
#define SINGLETON_H
#include <QMutex>
// 单例 - 懒汉式/饿汉式公用
class Singleton
{
public:
static Singleton* GetInstance();
private:
Singleton() {} // 构造函数(被保护)
Singleton(Singleton const &); // 无需实现
Singleton& operator = (const Singleton &); // 无需实现
private:
static Singleton *m_pSingleton; // 指向单例对象的指针
static QMutex m_mutex; // 锁
};
#endif // SINGLETON_H
// singleton.cpp
#include "singleton.h"
// 单例 - 懒汉式
Singleton *Singleton::m_pSingleton = nullptr;
QMutex Singleton::m_mutex;
Singleton *Singleton::GetInstance()
{
if (!m_pSingleton) {
Singleton::m_mutex.lock();
if (!m_pSingleton) {
Singleton::m_pSingleton = new Singleton();
}
Singleton::m_mutex.unlock();
}
return Singleton::m_pSingleton;
}
优点:第一次调用才初始化,避免内存浪费。
缺点:非多线程安全。必须加锁才能保证单例,但加锁会影响效率。
饿汉式
// singleton.h
#ifndef SINGLETON_H
#define SINGLETON_H
// 单例 - 懒汉式/饿汉式公用
class Singleton
{
public:
static Singleton* GetInstance();
private:
Singleton() {} // 构造函数(被保护)
Singleton(Singleton const &); // 无需实现
Singleton& operator = (const Singleton &); // 无需实现
private:
static Singleton *m_pSingleton; // 指向单例对象的指针
};
#endif // SINGLETON_H
// singleton.cpp
#include "singleton.h"
// 单例 - 饿汉式
Singleton *Singleton::m_pSingleton = new Singleton();
Singleton *Singleton::GetInstance()
{
return m_pSingleton;
}
优点:多线程安全。没有加锁,执行效率会提高。
缺点:类加载时就初始化,浪费内存。
资源释放
资源释放分两种:
1、主动释放(手动调用接口来释放资源);
2、自动释放(由程序自己释放)。
要手动释放资源,添加一个 static 接口:
// 单例 - 主动释放
static void DestoryInstance()
{
if (m_pSingleton != nullptr) {
delete m_pSingleton;
m_pSingleton = nullptr;
}
}
然后在需要释放的时候,手动调用该接口:
Singleton::GetInstance()->DestoryInstance();