特点
保证一个类仅有一个实例,并提供一个访问它的全局访问点,该实例被所有程序模块共享
懒汉式
特点
第一次调用才初始化 避免浪费内存
必须加锁才能保证单例 但是加锁影响效率
demo
//
// Created by xatusec on 2019/12/3.
//
//.h
#ifndef SINGLETON_SINGLETON_H
#define SINGLETON_SINGLETON_H
#include <iostream>
class Singleton
{
public:
static Singleton * GetInstance();
private:
Singleton();
static Singleton *m_pInstance;
};
#endif //SINGLETON_SINGLETON_H
//.cpp
#include "Singleton.h"
Singleton *Singleton::GetInstance()
{
if(m_pInstance == nullptr)
{
m_pInstance = new Singleton();
}
return m_pInstance;
}
Singleton::Singleton()
{
std::cout << "Singleton()" << std::endl;
}
Singleton *Singleton::m_pInstance = nullptr;
//.main
#include "Singleton.h"
#include<iostream>
using namespace std;
int main()
{
Singleton *p1 = Singleton::GetInstance();
Singleton *p2 = Singleton::GetInstance();
cout << "p1 address:"<< p1 <<endl;
cout << "p2 address:"<< p2 << endl;
}
结果
两者地址相同 保证指向的是在内存中的同一个空间 实现了一个类只初始化一个实例
不重写拷贝构造/运算符重载存在问题
没有完全保证一个类只有一个实例(没有重写/禁用拷贝构造和运算符重载)改写main中的代码 结果如下
更改main.cpp为
#include "Singleton.h"
#include<iostream>
using namespace std;
int main()
{
Singleton* p1 = Singleton::GetInstance();
Singleton* p2 = Singleton::GetInstance();
cout << "p1 address:" << p1 << endl;
cout << "p2 address:" << p2 << endl;
Singleton p3(*p1);
Singleton p4 = *p1;
cout << "p3 address:" << &p3 << endl;
cout << "p4 address:" << &p4 << endl;
}
结果为
很明显 一个类生成了三个实例,不符合单例模式的要求
重写/删除拷贝构造个运算符重载
重写Singleton中拷贝构造函数和运算符重载
#include <iostream>
class Singleton
{
public:
static Singleton* GetInstance();
private:
Singleton(const Singleton& Single);
void operator= (const Singleton& Single);
Singleton();
static Singleton* m_pInstance;
};
保险起见 删除上述函数
#include <iostream>
class Singleton
{
public:
static Singleton* GetInstance();
private:
Singleton(const Singleton& Single) = delete;
void operator= (const Singleton& Single) = delete;
Singleton();
static Singleton* m_pInstance;
};
线程安全/内存泄漏问题
多线程下的该类可能会引发竞态条件
第一个线程正在判断全局指针是否为空,此时类尚未实例化,所以全局指针为空,其他线程到此 判断后发现指针为空,此时第一个线程才实例化了第一个类,故此,可能违背单例模式的原则,一个类实例化了多个对象出来。
解决方法
使用加锁和智能指针的改良方案
在这里插入代码片