单例模式的概念:
整个项目中,有某个或者某些特殊的类,只能创建一个属于该类的对象。
下面是单例类的实现代码:
#include <iostream>
using namespace std;
class A {
private:
A() {}
static A* m_A;
public:
static A* GetInstance() {
if (m_A == NULL) {
m_A = new A();
static B cl;
}
return m_A;
}
//释放对象
class B {
public:
~B() {
if (A::m_A) {
delete A::m_A;
A::m_A = NULL;
}
}
};
void func() {
std::cout << "ww" << std::endl;
}
};
//静态成员的初始化操作
A* A::m_A = NULL;
void main() {
A *p_a = A::GetInstance();
A *p_b = A::GetInstance();
//创建再多的指针也还是同一个地址;
}
1.将类的构造函数设置为私有的,同时申请静态成员函数(公有)和静态成员变量(私有);
2.怎么释放申请的单例类对象的内存呢,在类中嵌套一个类对象,在嵌套的类对象中析构函数中 释放申请的变量。(将嵌套类对象放在大类的静态成员函数中(以静态对象存在哦!确保对象是在程序运行结束后释放的));
当单例碰到了多线程,会有什么问题,比如两个线程中同时访问GetInstance(),这就会出现问题,会同时创建多个对象????
那解决措施自然 会想到 互斥量来锁一下来解决这个问题!
GetInstance()函数是只是初始化会被调用一次的,所以如下的操作不太行,效率不行!
#include <iostream>
#include <mutex>
using namespace std;
mutex myMutex;
//懒汉模式
class Singelton
{
public:
static Singelton * getInstance() {
lock_guard<mutex> myLockGua(myMutex);
if (instance == NULL) {
instance = new Singelton;
}
return instance;
}
private:
Singelton() {}
static Singelton *instance;
};
Singelton * Singelton::instance = NULL;
所以就有了双重锁定解决效率问题!
#include <iostream>
#include <mutex>
using namespace std;
mutex myMutex;
class Singelton
{
public:
static Singelton * getInstance() {
//双重锁定 提高效率
if (instance == NULL) {
lock_guard<mutex> myLockGua(myMutex);
if (instance == NULL) {
instance = new Singelton;
}
}
return instance;
}
private:
Singelton() {}
static Singelton *instance;
};
Singelton * Singelton::instance = NULL;
这样算是解决了问题!
同样的c++11给我们提供了一个解决方案 std::call_once 当然要结合std::once_flage 一起,具体操作就是 将只要初始化一次的语句,写入一个函数中,在调用这对类std 解决;代码如下:
once_flag g_flag;
class Singelton
{
public:
static void CreateInstance()//call_once保证其只被调用一次
{
instance = new Singelton;
}
//两个线程同时执行到这里,其中一个线程要等另外一个线程执行完毕
static Singelton * getInstance() {
call_once(g_flag, CreateInstance);
return instance;
}
private:
Singelton() {}
static Singelton *instance;
};
Singelton * Singelton::instance = NULL;
部分 代码 参考博客:https://blog.csdn.net/qq_38231713/article/details/106092538