单例模式
目的:有且保证只有一个实例
应用场景:写日志等
问题的来源:
在new是对象产生的直接来源,为了只有实例化一个对象,那么只能将构造函数私有化才能控制对象的个数。
在构造函数私有化后,需要提供一个方法,让程序获取对象。
具体代码:
/*懒汉式*/
#include"afxmt.h"//同步操作时需要包含的头文件
class CSingleton
{
public:
static CCriticalSection _cs;
static CSingleton * _instance;//全局唯一实例
private:
CSingleton()//私有化构造器
{
}
~CSingleton()
{
if (_instance != nullptr)//多线程会出现问题
{
delete _instance;
_instance = nullptr;
}
}
/**
*私有拷贝构造和赋值重载,保证唯一实例
*/
CSingleton(const CSingleton &);
CSingleton & operator = (const CSingleton &);
public:
static CSingleton* getInstance()//多线程会出现问题
{
if (_instance == nullptr)
{
_cs.Lock();
if (_instance == nullptr)
{
_instance = new CSingleton();
}
_instance = new CSingleton();
_cs.Unlock();
}
return _instance;
}
};
/*静态变量的初始化*/
CSingleton * CSingleton::_instance = nullptr;
CCriticalSection CSingleton::_cs;
其中私有化的成员变量:构造函数、拷贝构造,赋值重载。就是为了不能实例化对象。
if (_instance == nullptr)
{
_cs.Lock();
if (_instance == nullptr)
{
_instance = new CSingleton();
}
_instance = new CSingleton();
_cs.Unlock();
}
首先判定是否为空,不为空加锁,在判定是否为空。主要是因为:锁的开销很大 所以需要先判定是否为空。释放的时候需要判定是否为空 才能释放指针。
/*饿汉式*/
class CSingleton2
{
public:
static CCriticalSection _cs;
static CSingleton2 * _instance;//全局唯一实例
private:
CSingleton2()//私有化构造器
{
}
~CSingleton2()
{
delete _instance;
_instance = nullptr;
}
/**
*私有拷贝构造和赋值重载,保证唯一实例
*/
CSingleton2(const CSingleton2 &);
CSingleton2 & operator = (const CSingleton2 &);
public:
static CSingleton2* getInstance()//多线程会出现问题
{
return _instance;
}
};
/*静态变量的初始化*/
CSingleton2 * CSingleton2::_instance = new CSingleton2();
<span style="font-family: Arial, Helvetica, sans-serif;">上面代码 不需要加锁,是因为在类加载时候就会实例话对象,就不会实例化多个对象。</span>
测试代码:
#include <iostream>
#include "Singleton.h"
using namespace std;
int main()
{
<span style="white-space:pre"> </span>CSingleton *s1 = CSingleton::getInstance();
<span style="white-space:pre"> </span>CSingleton *s2 = CSingleton::getInstance();
<span style="white-space:pre"> </span>cout << "-----------懒汉式单例模式-----------"<< endl;
<span style="white-space:pre"> </span>cout << "单例1的地址:" << s1 << endl;
<span style="white-space:pre"> </span>cout << "单例2的地址:" << s2 << endl<<endl;
<span style="white-space:pre"> </span>CSingleton2 *s3 = CSingleton2::getInstance();
<span style="white-space:pre"> </span>CSingleton2 *s4 = CSingleton2::getInstance();
<span style="white-space:pre"> </span>cout << "-----------饿汉式单例模式-----------" << endl;
<span style="white-space:pre"> </span>cout << "单例1的地址:" << s3 << endl;
<span style="white-space:pre"> </span>cout << "单例2的地址:" << s4 << endl;
<span style="white-space:pre"> </span>getchar();
<span style="white-space:pre"> </span>return 0;
}
注意:
在多线程使用单例,还是需要加锁。