一、说明
单例模式中,实例什么时候释放是一个很严肃的问题,尤其是资源没有释放的情况。今天突然注意到了这个问题。
二、错误示范
2.1 看似没有错误的写法
我们先来看一份代码。
.h文件
#pragma once
#include <iostream>
using namespace std;
class SingletonPattern
{
private:
SingletonPattern();
public:
~SingletonPattern();
private:
static SingletonPattern* m_Instance;
public:
static SingletonPattern* GetInstance();
void display();
};
.cpp文件
#include "SingletonPattern.h"
SingletonPattern* SingletonPattern:: m_Instance = nullptr;
SingletonPattern::SingletonPattern()
{
cout << "创建单例模式对象!" << endl;
}
SingletonPattern::~SingletonPattern()
{
if (m_Instance != nullptr) {
delete m_Instance;
m_Instance = nullptr;
}
cout << "销毁单例模式对象!" << endl;
}
SingletonPattern *SingletonPattern::GetInstance()
{
if (m_Instance == nullptr) {
m_Instance = new SingletonPattern();
}
cout << "返回单例模式句柄!" << endl;
return m_Instance;
}
void SingletonPattern::display()
{
cout << "使用单例模式!" << endl;
}
测试
#include "SingletonPattern.h"
int main() {
SingletonPattern* m_Test = SingletonPattern::GetInstance();
m_Test->display();
cin.ignore();
return 0;
}
2.2 实际上隐藏巨大的bug
先不说这个析构函数会不会被调用,即使被调用后,析构函数和delete之间就会反复横跳(死循环),套娃是要不得的,程序是会崩溃的阿sir。
2.3 如何解决呢
当然又很多解决方式,例如
- 在外层直接手动delete
- getInstance里面不用new,而是直接static SingletonPattern m_Instance.
- 搞个垃圾回收的类Garbo
这里,我们重点说一下第三种的实现。
#pragma once
#include <iostream>
using namespace std;
class SingletonPattern
{
private:
SingletonPattern();
~SingletonPattern();
private:
static SingletonPattern* m_Instance;
public:
static SingletonPattern* GetInstance();
void display();
private:
class CGabor
{
public:
~CGabor(){
if (SingletonPattern::m_Instance){
delete SingletonPattern::m_Instance;
SingletonPattern::m_Instance = NULL;
}
}
};
static CGabor m_Gabor;
};
#include "single.h"
SingletonPattern* SingletonPattern:: m_Instance = nullptr;
SingletonPattern::CGabor SingletonPattern::m_Gabor;
SingletonPattern::SingletonPattern()
{
cout << "创建单例模式对象!" << endl;
}
SingletonPattern::~SingletonPattern()
{
//可在此释放某些占用的资源
}
SingletonPattern *SingletonPattern::GetInstance()
{
if (m_Instance == nullptr) {
m_Instance = new SingletonPattern();
}
cout << "返回单例模式句柄!" << endl;
return m_Instance;
}
void SingletonPattern::display()
{
cout << "使用单例模式!" << endl;
}
#include "single.h"
int main() {
SingletonPattern* m_Test = SingletonPattern::GetInstance();
m_Test->display();
cin.ignore();
return 0;
}