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

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

文章目录

  • 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;
}
  • 反汇编分析如下。

在这里插入图片描述

相关文章:

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

文章目录 25. 单例模式25.1. 饿汉式单例模式25.2. 懒汉式单例模式25.2.1. 解决方案125.2.2. 解决方案2 &#xff08;推荐写法&#xff09; 运行在VS2022&#xff0c;x86&#xff0c;Debug下。 25. 单例模式 单例即该类只能有一个实例。 应用&#xff1a;如在游戏开发中&#x…...

Django 做migrations时出错,解决方案

在做migrations的时候&#xff0c;偶尔会出现出错。 在已有数据的表中新增字段时&#xff0c;会弹出下面的信息 运行这个命令时 python manage.py makemigrationsTracking file by folder pattern: migrations It is impossible to add a non-nullable field ‘example’ to …...

QT::QNetworkReply类readAll()读取不到数据的可能原因

程序中&#xff0c;当发送请求时&#xff0c;并没有加锁&#xff0c;而是在响应函数中加了锁&#xff0c;导致可能某个请求的finished信号影响到其他请求响应数据的读取 connect(reply,&QNetworkReply::finished,this,&Display::replyFinished);参考这篇文章&#xff…...

vxe-form-design 表单设计器的使用

vxe-form-design 在 vue3 中表单设计器的使用 查看官网 https://vxeui.com 安装 npm install vxe-pc-ui // ... import VxeUI from vxe-pc-ui import vxe-pc-ui/lib/style.css // ...// ... createApp(App).use(VxeUI).mount(#app) // ...使用 github vxe-form-design 用…...

【Linux】TCP协议【上】{协议段属性:源端口号/目的端口号/序号/确认序号/窗口大小/紧急指针/标记位}

文章目录 1.引入2.协议段格式4位首部长度16位窗口大小32位序号思考三个问题【demo】标记位URG: 紧急指针是否有效提升某报文被处理优先级【0表示不设置1表示设置】ACK: 确认号是否有效PSH: 提示接收端应用程序立刻从TCP缓冲区把数据读走RST: 对方要求重新建立连接; 我们把携带R…...

php之sql代码审计

1 SQL注入代码审计流程 1.1 反向查找流程 通过可控变量(输入点)回溯危险函数 查找危险函数确定可控变量 传递的过程中触发漏洞 1.2 反向查找流程特点 暴力&#xff1a;全局搜索危险函数 简单&#xff1a;无需过多理解目标网站功能与架构 快速&#xff1a;适用于自动化代码审…...

【Java用法】java中计算两个时间差

java中计算两个时间差 不多说&#xff0c;直接上代码&#xff0c;可自行查看示例 package org.example.calc;import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.time.temporal.ChronoUnit;public class MinusTest {public static void…...

tinymce富文本编辑器使用

安卓富文本编辑器&#xff1a;npm i tinymce/tinymce-vue 当前项目中富文本是放在一个dialog中&#xff0c;因此部分样式会有层叠问题&#xff0c;该组件样式部分不添加scope。这里图片上传只是前端静态数据展示收集。 <template><div class"desc-editor"…...

Java——接口后续

1.Comparable 接口 在Java中&#xff0c;我们对一个元素是数字的数组可以使用sort方法进行排序&#xff0c;如果要对一个元素是对象的数组按某种规则排序&#xff0c;就会用到Comparable接口 当实现Comparable接口后&#xff0c;sort会自动调用Comparable接口里的compareTo 方法…...

最新上市公司控制变量大全(1413+指标)1990-2023年

数据介绍&#xff1a;根据2023年上市公司年报数据进行更新&#xff0c;包括基本信息、财务指标、环境、社会与治理、数字化转型、企业发展、全要素生产率等1413指标。数据范围&#xff1a;A股上市公司数据年份&#xff1a;1990-2023年指标数目&#xff1a;1413个指标&#xff0…...

jmeter多用户并发登录教程

有时候为了模拟更真实的场景&#xff0c;在项目中需要多用户登录操作&#xff0c;大致参考如下 jmx脚本&#xff1a;百度网盘链接 提取码&#xff1a;0000 一&#xff1a; 单用户登录 先使用1个用户登录&#xff08;先把1个请求调试通过&#xff09; 发送一个登录请求&…...

【高频】redis快的原因

相关问题&#xff1a; 1.为什么Redis能够如此快速地进行数据存储和检索&#xff1f; 2.Redis作为内存数据库,其内存存储有什么优势吗? 3.Redis的网络模型有何特点,如何帮助提升性能? 一、问题回答 Redis使用了内存数据结构&#xff0c;例如字符串、哈希表、列表、集合、有…...

hive3从入门到精通(一)

Hive3入门至精通(基础、部署、理论、SQL、函数、运算以及性能优化)1-14章 第1章:数据仓库基础理论 1-1.数据仓库概念 数据仓库&#xff08;英语&#xff1a;Data Warehouse&#xff0c;简称数仓、DW&#xff09;,是一个用于存储、分析、报告的数据系统。 数据仓库的目的是构…...

c++编程(15)——list的模拟实现

欢迎来到博主的专栏——c编程 博主ID&#xff1a;代码小豪 文章目录 前言list的数据结构list的默认构造尾插与尾删iterator插入和删除构造、析构、赋值copy构造initializer_list构造operator 析构函数 前言 受限于博主当前的技术水平&#xff0c;暂时还不能模拟实现出STL当中用…...

【深度学习】吸烟行为检测软件系统

往期文章列表&#xff1a; 【YOLO深度学习系列】图像分类、物体检测、实例分割、物体追踪、姿态估计、定向边框检测演示系统【含源码】【深度学习】YOLOV8数据标注及模型训练方法整体流程介绍及演示【深度学习】行人跌倒行为检测软件系统【深度学习】火灾检测软件系统【深度学…...

​你见过哪些不过度设计的优秀APP?​

优联前端https://ufrontend.com/ 提供一站式企业前端解决方案 “每日故宫”是一款以故宫博物院丰富的藏品为基础&#xff0c;结合日历形式展示每日精选藏品的移动应用。通过这款应用&#xff0c;用户可以随时随地欣赏到故宫的珍贵藏品&#xff0c;感受中华五千年文化的魅力。…...

全栈:session用户会话信息,用户浏览记录实例

PHP中的session是一种存储机制&#xff0c;它允许您存储和跟踪用户在访问Web应用程序时的信息。会话通常用于存储用户特定的数据&#xff0c;如用户ID、购物车内容、用户偏好设置等&#xff0c;这些数据需要在多个页面请求之间保持不变。 session详解 1. 会话是如何工作的 会…...

设计模式--》 装饰模式的应用

装饰模式的定义&#xff1a; 装饰模式&#xff08;Decorator Pattern&#xff09;是一种结构型设计模式&#xff0c;它允许你动态地给一个对象添加一些额外的职责。就增加功能来说&#xff0c;装饰模式相比生成子类更为灵活。 何时应用装饰模式&#xff1f; 1.当需要动态地给…...

深入解析Web前端三大主流框架:Angular、React和Vue

Web前端三大主流框架分别是Angular、React和Vue。下面我将为您详细介绍这三大框架的特点和使用指南。 Angular 核心概念: 组件(Components): 组件是Angular应用的构建块,每个组件由一个带有装饰器的类、一个HTML模板、一个CSS样式表组成。组件通过输入(@Input)和输出(…...

ch3运输层--计算机网络期末复习(持续更新中)

运输层位于网络层之上 运输层协议提供的某些服务受到网络层协议的限制。比如,时限和带宽保证。 运输层也提供自己的特殊服务。比如,可靠数据传输服务,安全性服务。 网络层:两个主机之间的逻辑通信 运输层:两个进程之间的逻辑通信 网络地址:主机的标识(IP地址) 传输地址: …...

mysql中的内连接与外连接

在MySQL中&#xff0c;内连接和外连接是用于从多个表中检索数据的两种不同的连接方式。 内连接&#xff08;INNER JOIN&#xff09;&#xff1a; 内连接返回两个表之间匹配的行。它只返回两个表中共同匹配的行&#xff0c;如果在一个表中没有匹配到对应的行&#xff0c;则不会显…...

0基础认识C语言(理论+实操 2)

小伙伴们大家好&#xff0c;今天也要撸起袖子加油干&#xff01;万事开头难&#xff0c;越学到后面越轻松~ 话不多说&#xff0c;开始正题~ 前提回顾&#xff1a; 接上次博客&#xff0c;我们学到了转义字符&#xff0c;最后留下两个转义字符不知道大家有没有动手尝试了一遍&a…...

ChatGPT的基本原理是什么?又该如何提高其准确性?

在深入探索如何提升ChatGPT的准确性之前&#xff0c;让我们先来了解一下它的工作原理吧。ChatGPT是一种基于深度学习的自然语言生成模型&#xff0c;它通过预训练和微调两个关键步骤来学习和理解自然语言。 在预训练阶段&#xff0c;ChatGPT会接触到大规模的文本数据集&#x…...

云计算OpenStack基础

1.什么是虚拟化&#xff1f; •虚拟化是云计算的基础。 •虚拟化是指计算元件在虚拟的而不是真实的硬件基础上运行。 •虚拟化将物理资源转变为具有可管理性的逻辑资源&#xff0c;以消除物理结构之间的隔离&#xff0c;将物理资源融为一个整体。虚拟化是一种简化管理和优化…...

[10] CUDA程序性能的提升 与 流

CUDA程序性能的提升 与 流 1. CUDA程序性能的提升 在本节中,我们会看到用来遵循的基本的一些性能来提升准则,我们会逐一解释它们1.1 使用适当的块数量和线程数量 研究表明,如果块的数量是 GPU 的流多处理器数量的两倍,则会给出最佳性能,不过,块和线程的数量与具体的算法…...

TH方程学习(1)

一、背景介绍 根据CW方程的学习&#xff0c;CW方程的限制条件为圆轨道&#xff0c;不考虑摄动&#xff0c;二者距离相对较小。TH方程则可以将物体间的相对运动推广到椭圆轨道的二体运动模型&#xff0c;本部分将结合STK的仿真功能&#xff0c;联合考察TH方程的有用性&#xff…...

【九十七】【算法分析与设计】图论,迷宫,1207. 大臣的旅费,走出迷宫,石油采集,after与迷宫,逃离迷宫,3205. 最优配餐,路径之谜

1207. 大臣的旅费 - AcWing题库 很久以前&#xff0c;TT 王国空前繁荣。 为了更好地管理国家&#xff0c;王国修建了大量的快速路&#xff0c;用于连接首都和王国内的各大城市。 为节省经费&#xff0c;TT 国的大臣们经过思考&#xff0c;制定了一套优秀的修建方案&#xff0c;…...

【Tools】SpringBoot工程中,对于时间属性从后端返回到前端的格式问题

Catalog 时间属性格式问题一、需求二、怎么使用 时间属性格式问题 一、需求 对于表中时间字段&#xff0c;后端创建对应的实体类的时间属性需要设定格式&#xff08;默认的格式不方便阅读&#xff09;&#xff0c;再返回给前端。 二、怎么使用 导入jackson相关的坐标&#x…...

算法训练营day35

题目1&#xff1a;122. 买卖股票的最佳时机 II - 力扣&#xff08;LeetCode&#xff09; 贪心算法思路很简单&#xff0c;就是把每一天的利润都算出来&#xff0c;然后把整的加起来就是结果 class Solution { public:int maxProfit(vector<int>& prices) {int resu…...

代码随想录-Day23

669. 修剪二叉搜索树 方法一&#xff1a;递归 class Solution {public TreeNode trimBST(TreeNode root, int low, int high) {if (root null) {return null;}if (root.val < low) {return trimBST(root.right, low, high);} else if (root.val > high) {return trimBS…...