当前位置: 首页 > 网络知识

C++ 设计模式之单例模式

时间:2026-01-29 09:24:52

设计模式之单例模式
  保证一个类仅有一个实例,并提供一个访问他的全局访问点。通常我们可以让一个全局变量使得一个对象被访问,但它不能防止你实例化多个对象。一个最好的办法就是,让类自身负责保存它的唯一实例。这个类可以保证没有其他实例可以被创建,并且可以提供一个访问该实例的接口。其UML图如下:

其示例代码如下:

1 // SingeltonModel.h文件 2 #pragma once 3 // 线程不安全类 4 class Singelton 5 8 static Singelton * m_singel; 9 public: 10 static Singelton * getInstance() 11 17 return m_singel; 18 } 19 }; 20 Singelton * Singelton::m_singel = nullptr;

测试代码如下:

1 #include <iostream> 2 #include "SingeltonModel.h" 3 4 int main() 5

测试结果如下图:

以上代码是有安全隐患的,如果该类在多线程中使用的话。当多个线程都第一次访问该类的是实例的时候有可能会出现创建两个实例,这样就出现内存泄漏了。并且两次的到的实例不是同一个,如下代码:

1 #include <iostream> 2 #include <thread> 3 #include <Windows.h> 4 #include "SingeltonModel.h" 5 6 void func1() 7 12 13 void func2() 14 19 20 int main() 21

输出结果如下图:

  由上图可看出,创建了两次实例,两个线程得到的实例并不是同一个。这是因为两个线程同时运行,当调用getInstance()时,实例并没有创建,于是两个线程都进入了创建实例的代码块,于是就创建了两个实例。而第一个被创建的实例被顶替后也没有被释放,这就是内存泄漏,还有先调用到创建实例的线程还得到了错误的实例,这样会造成逻辑错误的。

  解决办法有两种,一种办法是在所有要访问该类实例的代码执行前该类先创建实例,另一种是在该类的访问实例的代码中加入线程同步的内容。实例代码如下:

方法一:

1 #include <iostream> 2 #include <thread> 3 #include <Windows.h> 4 #include "SingeltonModel.h" 5 6 void func1() 7 12 13 void func2() 14 19 20 int main() 21

输出结果如下图:

方法二:

1 // SingeltonModel.h文件 2 #include <mutex> 3 #pragma once 4 5 // 线程安全类 6 class SingeltonThread 7 10 static SingeltonThread * m_instance; 11 static std::mutex m_mutex; 12 public: 13 static SingeltonThread * getInstance() 14 22 return m_instance; 23 } 24 }; 25 SingeltonThread * SingeltonThread::m_instance = nullptr; 26 std::mutex SingeltonThread::m_mutex;

测试代码如下:

1 #include <iostream> 2 #include <thread> 3 #include <Windows.h> 4 #include "SingeltonModel.h" 5 6 void func1() 7 12 13 void func2() 14 19 20 int main() 21

输出结果如下图:

  这两种方法都各有优势,方法一实现简单,但在复杂的系统中不太安全。方法二实现稍微复杂,而且每次访问实例都要lock(mutex),消耗更大。但是方法二在任何情况下都很安全。总之方法一适合在系统不是太复杂的情况下使用,方法二在系统比较复杂的情况下使用。



上一篇:C++ wchar_t char wstring string 转换
下一篇:C++ 设计模式之备忘录模式
  • 英特尔与 Vertiv 合作开发液冷 AI 处理器
  • 英特尔第五代 Xeon CPU 来了:详细信息和行业反应
  • 由于云计算放缓引发扩张担忧,甲骨文股价暴跌
  • Web开发状况报告详细介绍可组合架构的优点
  • 如何使用 PowerShell 的 Get-Date Cmdlet 创建时间戳
  • 美光在数据中心需求增长后给出了强有力的预测
  • 2027服务器市场价值将接近1960亿美元
  • 生成式人工智能的下一步是什么?
  • 分享在外部存储上安装Ubuntu的5种方法技巧
  • 全球数据中心发展的关键考虑因素
  • 英特尔与 Vertiv 合作开发液冷 AI 处理器

    英特尔第五代 Xeon CPU 来了:详细信息和行业反应

    由于云计算放缓引发扩张担忧,甲骨文股价暴跌

    Web开发状况报告详细介绍可组合架构的优点

    如何使用 PowerShell 的 Get-Date Cmdlet 创建时间戳

    美光在数据中心需求增长后给出了强有力的预测

    2027服务器市场价值将接近1960亿美元

    生成式人工智能的下一步是什么?

    分享在外部存储上安装Ubuntu的5种方法技巧

    全球数据中心发展的关键考虑因素