Singleton单例模式
# Singleton单例模式
Owner: -QVQ-
创建型
通过单例模式的设计,使得创建的类在当前进程中只有一个实例,并提供一个全局性的访问点,这样可以规避因频繁创建对象而导致的内存飙升情况。
三个要点:
1)私有化构造函数:这样外界就无法自由地创建类对象,进而阻止了多个实例的产生。
2)类定义中含有该类的唯一静态私有对象:静态变量存放在全局存储区,且是唯一的,供所有对象使用。
3)用公有的静态函数来获取该实例:提供了访问接口。
1)懒汉式:在使用类对象(单例实例)时才会去创建它,不然就懒得去搞。
2)饿汉式:单例实例在类装载时构建,有可能全局都没使用过,但它占用了空间,就像等着发救济粮的饿汉提前排好队等吃的一样。
实现单例模式通常面临两个问题,线程安全和内存泄漏。针对线程安全,可通过双重检测锁的方式来解决;针对内存泄漏,可通过资源管理的方式来解决,如智能指针和静态嵌套类
# 一、线程安全的懒汉式实现:
# 智能指针+锁
- 用锁实现需要时创建空间
- 用智能指针实现程序结束时释放空间
#include <iostream>
#include <mutex>
using namespace std;
class Singleton
{
public:
// 公有接口获取唯一实例
static shared_ptr<Singleton> getInstance() {
lock_guard<mutex> l(m_mutex);
if (instance == nullptr) {// 若为空则创建
instance.reset(new Singleton(), [](Singleton* x) {
delete x;
});
}
return instance;
}
private:
// 静态私有对象
static shared_ptr<Singleton> instance;
static mutex m_mutex;
};
// 初始化
shared_ptr<Singleton> Singleton::instance;
mutex Singleton::m_mutex;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# 嵌套类+锁
在类中定义一个删除类,再定义一个这个删除类的静态实例,当所有的类都释放了,会释放这个静态实例,从而调用删除类的析构函数释放空间
写这么麻烦,不如智能指针
// 单例模式演示类
class Singleton
{
public:
static Singleton* getInstance() {
if (instance == nullptr) {
lock_guard<mutex> l(m_mutex);
if (instance == nullptr) {
instance = new Singleton();
}
}
return instance;
}
private:
// 定义一个删除器
class Deleter {
public:
Deleter() {};
~Deleter() {
if (instance != nullptr) {
delete instance;
instance = nullptr;
}
}
};
// 删除器是嵌套类,当该静态对象销毁的时候,也会将单例实例销毁
static Deleter m_deleter;
private:
static Singleton* instance;
static mutex m_mutex;
};
// 初始化
Singleton* Singleton::instance = nullptr;
mutex Singleton::m_mutex;
Singleton::Deleter Singleton::m_deleter;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# ⭐局部对象
局部静态对象在多线程场景下的初始化行为,只有在首次访问时才会创建实例,后续不再创建而是获取
class Singleton
{
public:
// 公有接口获取唯一实例
static Singleton* getInstance() {
static Singleton instance;
return &instance;
}
};
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
# 线程安全的饿汉式实现
在一开始就分配好了空间,后续直接返回这个空间的地址就好
// 单例模式演示类
class Singleton
{
public:
// 公有接口获取唯一实例
static Singleton* getInstance() {
return instance;
}
private:
// 静态私有对象
static Singleton* instance;
};
// 初始化
Singleton* Singleton::instance = new Singleton();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
但有内存泄漏问题,解决方法:
- 智能指针
- 静态嵌套类
上次更新: 2025/02/21, 14:57:10