C++设计模式-单例模式,反汇编

news2025/1/17 23:23:53

文章目录

  • 25. 单例模式
    • 25.1. 饿汉式单例模式
    • 25.2. 懒汉式单例模式
      • 25.2.1. 解决方案1
      • 25.2.2. 解决方案2 (推荐写法)

运行在VS2022,x86,Debug下。

25. 单例模式

  • 单例即该类只能有一个实例。

  • 应用:如在游戏开发中,可以使用单例模式来管理各种资源,确保这些资源在整个游戏中只被加载和管理一次。

  • 实现

    • 将构造函数和析构函数私有,不允许外部构造或析构类对象。
    • 将拷贝构造函数、赋值运算符、移动构造函数和移动赋值运算符删除,不允许复制或移动类对象。
    • 需要有一个静态函数接口,返回唯一的静态实例。
  • 分类

    • 饿汉式单例模式:在main()开始前,实例就已经存在了。
    • 懒汉式单例模式:在第一次调用获取实例时才创建实例。

25.1. 饿汉式单例模式

  • 代码如下。
class Singleton
{
private:
    Singleton() {} //私有构造函数
    ~Singleton() {} //私有析构函数

    Singleton(const Singleton&) = delete; //删除拷贝构造函数
    Singleton& operator=(const Singleton&) = delete; //删除赋值运算符
    Singleton(Singleton&&) = delete; //删除移动构造函数
    Singleton & operator=(Singleton&&) = delete; //删除移动赋值运算符
 
private:
    static Singleton instance; //静态成员变量,存储实例

public:
    static Singleton* getInstance() //静态成员函数,获取实例
    {
        return &instance;
    }
};

Singleton Singleton::instance; //静态成员变量实例化

int main()
{
    Singleton* s1 = Singleton::getInstance();
    Singleton* s2 = Singleton::getInstance();
    return 0;
}
  • 在main()处设置断点,监视窗口如下,实例的内存地址为0x00E0C138。

在这里插入图片描述

  • 总结
    • 优点:线程安全,因为程序运行时就已经生成唯一的实例。
    • 缺点:不是按需创建实例。

25.2. 懒汉式单例模式

  • 新增一个静态函数接口,用于释放实例内存。
  • 代码如下。
class Singleton
{
private:
    Singleton(){} //私有构造函数
    ~Singleton(){} //私有析构函数
 
    Singleton(const Singleton&) = delete; //删除拷贝构造函数
    Singleton& operator=(const Singleton&) = delete; //删除赋值运算符
    Singleton(Singleton&&) = delete; //删除移动构造函数
    Singleton & operator=(Singleton&&) = delete; //删除移动赋值运算符
 
private:
    static Singleton* instance; //静态成员变量,存储实例
 
public:
    static Singleton* getInstance() //静态成员函数,获取实例
    {
        if (instance == nullptr)
            instance = new Singleton();
        return instance;
    }
 
    static void deleteInstance() //静态成员函数,释放实例
    {
        if (instance != nullptr)
        {
            delete instance;
            instance = nullptr;
        }
    }
};
 
Singleton* Singleton::instance = nullptr; //静态成员变量定义和初始化
 
int main() 
{
    Singleton* s1 = Singleton::getInstance();
    Singleton* s2 = Singleton::getInstance();
 
    Singleton::deleteInstance();
    return 0;
}
  • 在main()处设置断点,监视窗口如下,此时未生成实例。

在这里插入图片描述

  • 第一次调用getInstance()获取实例时,生成实例,实例的内存地址为0x00E16A08。

在这里插入图片描述

  • 总结
    • 优点:按需创建实例。
    • 缺点:
      • 不是线程安全,如两个线程同时调用getInstance()获取实例,同时运行到判断instance是否为nullptr的if语句,并且instance并未创建,那么两个线程都会创建一个实例。
      • 内存释放问题,在程序执行结束时,调用deleteInstance()释放实例内存,但是要确保delete之后,没有代码再调用getInstance()或者访问已释放的内存,存在安全隐患。

25.2.1. 解决方案1

  • 针对线程安全问题,加锁。
  • 针对内存释放问题,对于全局变量或静态变量,main()返回后会调用析构函数。基于此,可以定义一个静态成员变量,用于释放实例内存。
  • 代码如下。
mutex m;

class Singleton
{
private:
    Singleton() {} //私有构造函数
    ~Singleton() {} //私有析构函数

    Singleton(const Singleton&) = delete; //删除拷贝构造函数
    Singleton& operator=(const Singleton&) = delete; //删除赋值运算符
    Singleton(Singleton&&) = delete; //删除移动构造函数
    Singleton& operator=(Singleton&&) = delete; //删除移动赋值运算符

    static Singleton* instance; //静态成员变量,存储实例

    class Garbo //在析构函数中释放实例
    {
    public:
        ~Garbo()
        {
            if (Singleton::instance != nullptr)
            {
                delete instance;
                instance = nullptr;
            }
        }
    };

    static Garbo garbo; //静态成员变量,在程序执行结束时,系统会调用它的析构函数

public:
    static Singleton* getInstance() //静态成员函数,获取实例
    {
        if (instance == nullptr) //加锁前判断,这样如果实例存在,就不需加锁了
        {
            lock_guard<mutex>lock(m); //创建实例前加锁
            if (instance == nullptr)
                instance = new Singleton();
        }
       
        return instance;
    }
};

Singleton* Singleton::instance = nullptr; //静态成员变量定义和初始化

int main()
{
    Singleton* s1 = Singleton::getInstance();
    Singleton* s2 = Singleton::getInstance();

    return 0;
}

25.2.2. 解决方案2 (推荐写法)

  • 在静态函数接口里,定义局部静态变量,存储实例。那么它会在第一次调用获取实例时才创建,可以按需创建实例。同时内部__Init_thread_header()和_Init_thread_footer()可以保证局部静态变量的初始化是线程安全的。
  • 代码如下。
class Singleton
{
private:
    Singleton() {} //私有构造函数
    ~Singleton() {} //私有析构函数

    Singleton(const Singleton&) = delete; //删除拷贝构造函数
    Singleton& operator=(const Singleton&) = delete; //删除赋值运算符
    Singleton(Singleton&&) = delete; //删除移动构造函数
    Singleton& operator=(Singleton&&) = delete; //删除移动赋值运算符
   
public:
    static Singleton* getInstance() //静态成员函数,获取实例
    {
        static Singleton instance; //局部静态成员变量,存储实例
        return &instance;
    }
};

int main()
{
    Singleton* s1 = Singleton::getInstance();
    Singleton* s2 = Singleton::getInstance();

    return 0;
}
  • 反汇编分析如下。

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1790556.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

网易有道QAnything使用CPU模式和openAI接口安装部署

网易有道QAnything可以使用本地部署大模型&#xff08;官网例子为qwen&#xff09;也可以使用大模型接口(OPENAI或者其他大模型AI接口 )的方式&#xff0c;使用在线大模型API接口好处就是不需要太高的硬件配置。 本机环境windows11 首先安装WSL环境, 安装方法参考https://zhuan…

如何在springboot项目中使用Mybatisplus

文章目录 1.mybatisplus的作用2.mybatisplus使用流程2.1pom.xml文件中增加依赖&#xff08;点击右上角蓝色按钮下载依赖&#xff09;2.2navicat新建数据库&#xff0c;增加application.properties数据库配置2.3 启动类添加注解&#xff0c;增加mapper包操作数据库2.5添加实体类…

外资企业使用卓豪Zoho CRM优势有哪些?

外资企业在中国市场的竞争愈发激烈&#xff0c;为了在众多本土与国际对手中脱颖而出&#xff0c;高效管理客户关系、提升销售业绩、并实现市场精准定位成为了企业不可或缺的竞争力。在这场数字化转型的浪潮中&#xff0c;卓豪Zoho CRM以其卓越的性能和全面的功能&#xff0c;成…

Nginx配置详细解释:(1)全局配置

自启动安装nginx:前面博客有解释 systemctl stop firewalld setenforce 0 [rootNode1 ~]#:mkdir /data [rootNode1 ~]#:cd /data [rootNode1 data]#:yum -y install gcc pcre-devel openssl-devel zlib-devel openssl openssl-devel [rootNode1 data]#:wget http://nginx.o…

【计算机网络】P3 计算机网络协议、接口、服务的概念、区别以及计算机网络提供的三种服务方式

目录 协议什么是协议协议是水平存活的协议的组成 接口服务服务是什么服务原语 协议与服务的区别计算机网络提供的服务的三种方式面向连接服务与无连接服务可靠服务与不可靠服务有应答服务与无应答服务 协议 什么是协议 协议&#xff0c;就是规则的集合。 在计算机网络中&…

反激变压器的漏感及其测量方式

绿色圈的是气隙&#xff0c;蓝色的弧线是那个线包&#xff0c;变压器的漏感&#xff0c;主要由磁力线向空气中散发&#xff0c;没有构成回路&#xff0c;线包自身的磁场&#xff0c;不参与能量传输&#xff0c;还有气隙等。 中间的气隙&#xff0c;由于此处磁力线穿过空气的导磁…

视频生成框架EasyAnimate正式开源!

近期&#xff0c;Sora模型的热度持续上涨&#xff0c;社区中涌现了一些类Sora的开源项目&#xff0c;这些项目均基于Diffusion Transformer结构&#xff0c;使用Transformer结构取代了UNet作为扩散模型的基线&#xff0c;旨在生成更长、更高分辨率、且效果更好的视频。EasyAnim…

Unity MiniCPM-V 让引擎拥有视觉

Unity MiniCPM-V 让引擎拥有视觉 前言项目Python环境布置Unity场景布置代码编写添加并设置脚本总结 鸣谢AI提示 前言 新发布的MiniCPM-V&#xff0c;忍不住玩一下&#xff0c;可以让之前制作的语音助手拥有一定的视觉能力&#xff08;不是OpenCV不行&#xff0c;而是AI更加符合…

【数据分享】中国第三产业统计年鉴(1991-2022)

大家好&#xff01;今天我要向大家介绍一份重要的中国第三产业统计数据资源——《中国第三产业统计年鉴》。这份年鉴涵盖了从1991年到2022年中国第三产业统计全面数据&#xff0c;并提供限时免费下载。&#xff08;无需分享朋友圈即可获取&#xff09; 数据介绍 每年的《中国…

数据结构的归并排序(c语言版)

一.归并排序的基本概念 1.基本概念 归并排序是一种高效的排序算法,它采用了分治的思想。它的基本过程如下: 将待排序的数组分割成两个子数组,直到子数组只有一个元素为止。然后将这些子数组两两归并,得到有序的子数组。不断重复第二步,直到最终得到有序的整个数组。 2.核心…

MES系统生产计划的实施流程

在工厂的生产运营中&#xff0c;首先需要制定生产计划&#xff0c;MES系统软件可以监控从原材料进入工厂到产品进入仓库的整个生产过程&#xff0c;记录生产过程中使用的材料&#xff0c;设备&#xff0c;产品检验数据和结果&#xff0c;以及生产时间&#xff0c;人员和其他信息…

项目-双人五子棋对战:匹配模块的实现(3)

完整代码见: 邹锦辉个人所有代码: 测试仓库 - Gitee.com 模块详细讲解 功能需求 匹配就类似于大家平常玩的王者荣耀这样的匹配功能, 当玩家点击匹配之后, 就会进入到一个匹配队列, 当匹配到足够数量的玩家后, 就会进入确认页. 在这里, 我们主要实现的是1 - 1匹配功能, 首先先…

PPP-B2b精密产品使用注意事项及分析

1、因为在使用PPP-B2b进行定轨的时候&#xff0c;发的精密轨道产品是B3频点的&#xff0c;需要改正的卫星质心&#xff08;Com&#xff09;与SP3精密星历对比。 2、PPP-B2b产品吸收了电离层误差&#xff0c;因此电离层提取方面与IGS电离层完全无法对其。 3、由于PPP-B2b产品精…

【微信小程序】初识小程序

项目结构 项目基本组成结构 页面基础组成结构 JSON 配置文件 App.json app.json是当前小程序的全局配置&#xff0c;包括了小程序的所有页面路径、窗口外观、界面表现、底部tab等。 在 pages 中加入路径&#xff0c;保存后&#xff0c;开发者工具可以自动帮我们创建对应的页…

SAS:什么时候用kcompress呀?

问题&#xff1a;如何截取ECGTPT变量中的后三个字符&#xff1f; 下图展示了以k开头的以及非k开头的substr函数和length函数&#xff0c;发现在UTF-8编码下&#xff0c;仅以k开头的函数能够截取成功。 释疑&#xff08;以下内容来自SAS Help&#xff09; SAS提供的字符函数…

微软云计算[2]之微软云关系数据库SQL Azure

微软云关系数据库SQL Azure SQL Azure概述SQL Azure关键技术SQL Azure数据库SQL Azure报表服务SQL Azure数据同步 SQL Azure和SQL Server对比 SQL Azure概述 SQL Azure是微软的云中关系型数据库。 SQL Azure数据库简化了多数据库的供应和部署。 SQL Azure还为用户提供内置的高…

FPGA新起点V1开发板(九)——流水灯

文章目录 一、模块框图二、代码编写三、注意点四、总结 一、模块框图 二、代码编写 endmodule下面需要敲出一个回车代码拼接是大括号 led < {led[2:0],led[3]}注意二进制和十进制 module flow_led(input sys_clk50,input rst_n,output reg [3:0] le…

探索 Adobe Illustrator 2023 (AI 2023) for Mac/Win——创意设计的强大工具

Adobe Illustrator 2023 (AI 2023) for Mac/Win 是一款在设计领域备受推崇的专业矢量图形编辑软件软件&#xff0c;为设计师们提供了无尽的创意可能性。 它具有强大而精确的绘图功能&#xff0c;让用户能够轻松绘制出各种复杂的图形、线条和形状。无论是简洁的图标设计还是精美…

STM32作业实现(八)触摸按键TPAD

目录 STM32作业设计 STM32作业实现(一)串口通信 STM32作业实现(二)串口控制led STM32作业实现(三)串口控制有源蜂鸣器 STM32作业实现(四)光敏传感器 STM32作业实现(五)温湿度传感器dht11 STM32作业实现(六)闪存保存数据 STM32作业实现(七)OLED显示数据 STM32作业实现(八)触摸按…

vscode中选择pytorch虚拟环境中库没有导入报错,但是本机命令行下载过了

这是下载成功的结果 这个时候你会发现matplotlib的库是下载过的&#xff0c;没法下载 这个的原因是你的matplotlib库是下载到本机的python上但是pytorch框架上的是没有这个库的&#xff0c;此时应该打开ananconda promopt 然后输入activate pytorch转换成pytorch环境 然后pip…