特殊类设计
# 只能在堆上创建对象的类
只能在堆上创建对象,也就是只能通过new操作符创建对象,方式如下:
- 将构造函数设置为私有,防止外部直接调用构造函数在栈上创建对象。
- 向外部提供一个获取对象的static接口,该接口在堆上创建一个对象并返回。
- 将拷贝构造函数设置为私有,并且只声明不实现,防止外部调用拷贝构造函数在栈上创建对象。
class HeapOnly {
public:
static unique_ptr<HeapOnly> CreateObj() {
return unique_ptr<HeapOnly>(new HeapOnly());
}
HeapOnly(const HeapOnly &hp) = delete;
HeapOnly &operator=(const HeapOnly &hp) = delete;
private:
HeapOnly() = default;
};
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
# 只能在栈上创建对象的类
- 将构造函数设置为私有,防止外部直接调用构造函数在堆上创建对象。
- 向外部提供一个获取对象的static接口,该接口在栈上创建一个对象并返回。
- 屏蔽
operator new
函数和operator delete
函数。
class StackOnly {
public:
static StackOnly CreateObj() {
return StackOnly();
}
private:
StackOnly() {}
void *operator new(size_t size) = delete;
void operator delete(void *p) = delete;
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
# 单例模式
单例模式指的就是一个类只能创建一个对象,该模式可以保证系统中该类只有一个实例,并提供一个访问它的全局访问点,该实例被所有程序模块共享。
# 饿汉模式
如果这个单例对象在多线程高并发环境下频繁使用,性能要求较高,那么显然使用饿汉模式来避免资源竞 争,提高响应速度更好。
- 将构造函数设置为私有,并将拷贝构造函数和赋值运算符重载函数设置为私有或删除,防止外部创建或拷贝对象。
- 提供一个指向单例对象的static指针,并在程序入口之前完成单例对象的初始化。
- 提供一个全局访问点获取单例对象。
// 饿汉模式
// 优点:简单
// 缺点:可能会导致进程启动慢,且如果有多个单例类对象实例启动顺序不确定。
class Singleton {
public:
static Singleton *GetInstance() {
return &m_instance;
}
private:
// 构造函数私有
Singleton() {};
// C++11
Singleton(Singleton const &) = delete;
Singleton &operator=(Singleton const &) = delete;
static Singleton m_instance;
};
Singleton Singleton::m_instance; // 在程序入口之前就完成单例对象的初始化
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 懒汉模式
如果单例对象构造十分耗时或者占用很多资源,比如加载插件啊, 初始化网络连接啊,读取文件啊等 等,而有可能该对象程序运行时不会用到,那么也要在程序一开始就进行初始化,就会导致程序启动时 非常的缓慢。 所以这种情况使用懒汉模式(延迟加载)更好。
- 将构造函数设置为私有,并将拷贝构造函数和赋值运算符重载函数设置为私有或删除,防止外部创建或拷贝对象。
- 提供一个指向单例对象的static指针,并在程序入口之前先将其初始化为空。
- 提供一个全局访问点获取单例对象。
// 懒汉模式
// 优点:第一次使用实例对象时,创建对象。进程启动无负载。多个单例实例启动顺序自由控制。
// 缺点:复杂
#include <iostream>
#include <mutex>
#include <thread>
using namespace std;
class Singleton {
public:
static Singleton *GetInstance() {
// 注意这里一定要使用Double-Check的方式加锁,才能保证效率和线程安全
if (nullptr == m_pInstance) {
m_mtx.lock();
if (nullptr == m_pInstance) {
m_pInstance = new Singleton();
}
m_mtx.unlock();
}
return m_pInstance;
}
// 实现一个内嵌垃圾回收类
class CGarbo {
public:
~CGarbo() {
if (Singleton::m_pInstance)
delete Singleton::m_pInstance;
}
};
// 定义一个静态成员变量,程序结束时,系统会自动调用它的析构函数从而释放单例对象
static CGarbo Garbo;
private:
// 构造函数私有
Singleton() {};
// 防拷贝
Singleton(Singleton const &);
Singleton &operator=(Singleton const &);
static Singleton *m_pInstance; // 单例对象指针
static mutex m_mtx; //互斥锁
};
Singleton *Singleton::m_pInstance = nullptr;
Singleton::CGarbo Garbo;
mutex Singleton::m_mtx;
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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
上次更新: 2025/02/07, 18:31:39