当前位置: 首页 > news >正文

C++设计模式单例模式(饿汉、懒汉模式)

文章目录

  • 单例模式
    • volatile关键字作用
    • std::atomic
    • std::memory_order_relaxed
    • GameConfig* tmp = m_instance.load(std::memory_order_relaxed);
    • std::memory_order_acquire
    • std::lock_guard\<std::mutex> lock(m_mutex);
    • std::memory_order_release和std::memory_order_relaxed的区别
    • m_instance.store(tmp, std::memory_order_relaxed);
    • 饿汉模式
    • 懒汉模式
    • 懒汉模式(进阶版)
    • 单例类UML图
    • 重点

单例模式

单例类除了只能创建一个该类对象外,在使用方面与普通类没什么区别

#include <atomic>
#include <mutex>// 游戏配置相关类
class GameConfig {private:GameConfig() {};GameConfig(const GameConfig& tmpobj);GameConfig& operator=(const GameConfig& tmpobj);~GameConfig() {};public:static GameConfig* getInstance() {GameConfig* tmp = m_instance.load(std::memory_order_relaxed);std::atomic_thread_fence(std::memory_order_acquire);if(tmp == nullptr) {std::lock_guard<std::mutex> lock(m_mutex);tmp = m_instance.load(std::memory_order_relaxed);if(tmp == nullptr) {tmp = new GameConfig();std::atomic_thread_fence(std::memory_order_release);m_instance.store(tmp, std::memory_order_relaxed);}}return tmp;}private:static atomic<GameConfig*> m_instance;static std::mutex m_mutex;
};std::atomic<GameConfig*> GameConfig::m_instance;
std::mutex GameConfig::m_mutex;

volatile关键字作用

在这里插入图片描述

std::atomic

在这里插入图片描述

std::memory_order_relaxed

在这里插入图片描述

GameConfig* tmp = m_instance.load(std::memory_order_relaxed);

在这里插入图片描述

std::memory_order_acquire

在这里插入图片描述

std::lock_guard<std::mutex> lock(m_mutex);

在这里插入图片描述

std::memory_order_release和std::memory_order_relaxed的区别

在这里插入图片描述

m_instance.store(tmp, std::memory_order_relaxed);

在这里插入图片描述

饿汉模式

程序一执行,不管是否调用了getInstance成员函数,这个单件类对象就已经被创建了(对象创建将不受多线程问题困扰)

对饿汉式单例类对象的使用,应该在程序入口函数开始执行后,例如main主函数开始执行后

//饿汉式
class GameConfig
{//......
private:GameConfig() {};GameConfig(const GameConfig& tmpobj);GameConfig& operator=(const GameConfig& tmpobj);~GameConfig() {};
public:static GameConfig* getInstance(){return m_instance;}
private:static GameConfig* m_instance;	 //指向本类对象的指针private://手工释放单例类对象引入的GameConfig类中的嵌套类(垃圾回收)class Garbo {public:~Garbo() {if (GameConfig::m_instance != nullptr){delete GameConfig::m_instance;GameConfig::m_instance = nullptr;}}};private:static Garbo garboobj;
};GameConfig* GameConfig::m_instance = new GameConfig();//趁静态成员变量定义的时机直接初始化是被允许的,即便GameConfig构造函数用private修饰
GameConfig::Garbo GameConfig::garboobj;

懒汉模式

程序执行后该单例类对象并不存在,只有第一次调用getInstance成员函数时,该单例类对象才会被创建,这种方式能够更好的控制单例类的创建时机,以免过早加载可能导致对内存等资源不必要的消耗(加入类GameConfig非常庞大的话)

//懒汉式
//游戏配置相关类
class GameConfig
{//......
private:GameConfig() {};GameConfig(const GameConfig& tmpobj);GameConfig& operator = (const GameConfig& tmpobj);~GameConfig() {};
public:static GameConfig* getInstance(){//std::lock_guard<std::mutex> gcguard(my_mutex);if (m_instance == nullptr){//这里再加锁//std::lock_guard<std::mutex> gcguard(my_mutex);//if (m_instance == nullptr)//{m_instance = new GameConfig();static Garbo garboobj;//}}return m_instance;}public://要手工调用才能释放内存static void freeInstance(){if (m_instance != nullptr){delete GameConfig::m_instance;GameConfig::m_instance = nullptr;}}private://手工释放单件类对象引入的GameConfig类中的嵌套类(垃圾回收)class Garbo {public:~Garbo() {if (GameConfig::m_instance != nullptr){delete GameConfig::m_instance;GameConfig::m_instance = nullptr;}}};private:static GameConfig* m_instance; //指向本类对象的指针 static Garbo garboobj;
};GameConfig* GameConfig::m_instance = nullptr; //在类外,某个.cpp源文件的开头位置,为静态成员变量赋值(定义并赋值)
GameConfig::Garbo GameConfig::garboobj;

懒汉模式(进阶版)

//懒汉式
//游戏配置相关类 
class GameConfig
{
private:GameConfig() {};GameConfig(const GameConfig& tmpobj);GameConfig& operator = (const GameConfig& tmpobj);~GameConfig() {};
public:static GameConfig* getInstance(){GameConfig* tmp = m_instance.load(std::memory_order_relaxed);std::atomic_thread_fence(std::memory_order_acquire);if (tmp == nullptr){std::lock_guard<std::mutex> lock(m_mutex);tmp = m_instance.load(std::memory_order_relaxed);if (tmp == nullptr){tmp = new GameConfig();static Garbo garboobj;std::atomic_thread_fence(std::memory_order_release);							m_instance.store(tmp, std::memory_order_relaxed);}}return tmp;}private://手工释放单件类对象引入的GameConfig类中的嵌套类(垃圾回收)class Garbo {public:~Garbo() {if (GameConfig::m_instance != nullptr){delete GameConfig::m_instance;GameConfig::m_instance = nullptr;}}};private:static atomic<GameConfig*> m_instance;static std::mutex m_mutex;
};std::atomic<GameConfig*> GameConfig::m_instance;
std::mutex GameConfig::m_mutex; 

单例类UML图

引入单例设计模式的实现意图:保证一个类仅有一个实例存在,同时提供能对该实例访问的全局方法(getInstance成员函数)

在这里插入图片描述

重点

不要在单例类的析构函数中引用其他单例类对象

之后我会持续更新,如果喜欢我的文章,请记得一键三连哦,点赞关注收藏,你的每一个赞每一份关注每一次收藏都将是我前进路上的无限动力 !!!↖(▔▽▔)↗感谢支持!

http://www.dtcms.com/a/323760.html

相关文章:

  • 基于 RabbitMQ 死信队列+TTL 实现延迟消息+延迟插件基本使用
  • 检索召回率优化探究五(BGE-M3 混合检索):基于LangChain0.3 集成Milvu2.5 向量数据库构建的智能问答系统
  • 【Matplotlib】中文显示问题
  • Vue3 组件化开发
  • 第4章 程序段的反复执行1 for语句P115练习题(题及答案)
  • 堆----3.数据流的中位数
  • 第4章 程序段的反复执行2 while语句P128练习题(题及答案)
  • 2025AI颠覆认知!解锁智能新纪元
  • Kubernetes 无法识别你定义的 `CronJob` 资源*逐步解决方案
  • AI推理的“灵魂五问”:直面2025算力鸿沟与中国的破局之路
  • PowerShell 入门系列(五):运行命令与命令剖析详解
  • 面试题-----Spring Cloud
  • n8n 入门指南:更适合跨境出海搞钱的AI智能体
  • 7天精通Coze智能体实操手册(Day 1)
  • 健全性测试(Sanity Testing):你软件的快速“体检” ✅(省时避坑,确保核心!)
  • 【三个数绝对值排序】2022-10-10
  • 心灵笔记:思考三部曲
  • 记忆化搜索@cache与自己创建一个字典进行存储有区别吗
  • 10.final, finally, finalize的区别
  • Level-MC 11“天空”
  • SpringBoot配置生效优先级
  • 实战:MyBatis 中 db.properties 的正确配置与最佳实践
  • 通过 SCP 和 LXD 配置迁移 CUDA 环境至共享(笔记)
  • HTML全景效果实现
  • C语言(长期更新)第9讲:操作符详解(一)
  • 《励曼旋耕》Liman Rotary Tillage
  • AI大模型模态特征详解
  • 功能测试中常见的面试题-一
  • 第4章 程序段的反复执行for语句P115练习题(题及答案)
  • C++面向对象及其特性