【C++】单例模式
文章目录
- 一. 介绍
- 二. 饿汉模式
- 三. 懒汉模式
- 四. 饿汉模式和懒汉模式对比
一. 介绍
单例模式是属于设计模式的一种,那什么是设计模式呢?
设计模式(Design Pattern)是一套被反复使用、多数人知晓的、经过分类的、代码设计经验的总结。为什么会产生设计模式这样的东西呢?就像人类历史发展会产生兵法一样。最开始部落之间打仗时都是人拼人的对
砍;后来春秋战国时期,七国之间经常打仗,就发现打仗也是有套路的,后来孙子就总结出了《孙子兵法》。孙子兵法就类似于一种打仗的“设计模式”。
使用设计模式的目的:为了代码可重用性、让代码更容易被他人理解、保证代码可靠性。 设计模式使代码编写真正工程化;设计模式是软件工程的基石脉络,如同大厦的结构一样。
一个类只能创建一个对象,即单例模式。该模式可以保证全局(一个进程中)只有一个唯一的实例对象,并提供一个访问它的全局访问点,该实例对象可以被所有线程访问到。比如在某个服务器程序中,该服务器的配置信息存放在一个文件中,这些配置数据由一个单例对象统一读取,然后服务进程中的其他对象再通过这个单例对象获取这些配置信息,这种方式简化了在复杂环境下的配置管理。
单例模式有两种实现:饿汉模式 和 懒汉模式
二. 饿汉模式
介绍:就是说不管你将来用或者不用,程序启动时(即 main 函数执行之前)就会创建单例对象。
特点:如果这个单例对象在多线程高并发环境下频繁使用,性能要求较高,那么显然使用饿汉模式来避免资源竞争,提高响应速度会更好。
实现方法:
- 构造函数私有:防止外部构造单例对象
- 防拷贝:禁用拷贝构造和赋值运算符重载函数,防止外部拷贝单例类对象
- 提供接口:在单例类中定义一个自身类的静态对象,这个对象就是单例对象,设计一个静态方法返回这个单例对象的地址给外部。
通过上面三步就能做到一个类只能创建一个对象,且同一进程下的各线程可以通过一个统一的接口拿到这个实例对象。
代码示例
class Singleton
{
public:// 提供访问单例对象的接口Singleton* GetInstance(){return &_inst;}private:// 单例对象static Singleton _inst;// 构造函数私有Singleton();// 放拷贝Singleton(const Singleton&) = delete;Singleton& operator=(Singleton&) = delete;
};// 单例对象存储在静态区中
// 在程序入口之前就完成单例对象的初始化
Singleton Singleton::_inst;
补充说明
三. 懒汉模式
介绍:如果单例对象构造十分耗时或者占用很多系统资源,比如加载数据库啊, 初始化网络连接啊,读取文件啊等等,而且有可能该对象在程序运行时不会用到,那么也要在程序一开始就进行初始化,就会导致程序启动时非常的缓慢。 所以这种情况使用懒汉模式(延迟加载)更好。
特点:第一次使用实例对象时,才会创建对象,进程启动无负载。且当系统中有多个单例实例时,启动顺序可以自由控制。
实现方法:
- 防构造:把构造函数私有,这样外部就不能实例化对象
- 防拷贝:禁用拷贝构造和赋值运算负重载函数,防止外部对我们的单例对象进行拷贝
- 提供一个
GetInstance()
接口获取单例对象
代码示例
class Singleton
{
public:static Singleton* GetInstance(){// 保护第一次需要加锁,后面都不需要加锁的场景,可以使用双检查加锁// 特点:第一次需要加锁,后面不再加锁,保护线程安全,同时提高了效率if (_inst == nullptr){_mtx.lock();if (_inst == nullptr){_inst = new Singleton();}_mtx.unlock();}return _inst;}private:static mutex _mtx;// 互斥锁static Singleton* _inst;// 单例对象指针// 防构造(把构造函数设为私有)Singleton() {};// 防拷贝(禁用拷贝构造)Singleton(const Singleton&) = delete;Singleton& operator=(const Singleton&) = delete;// 防拷贝(禁用赋值运算负重载)
};// 静态成员初始化
mutex Singleton::_mtx;
Singleton* Singleton::_inst = nullptr;
其他版本的懒汉
利用静态对象的特性:
- 静态对象的初始化语句只会执行一次
- 创建一个静态对象的过程是原子的
这样我们可以不用加锁,直接在接口中创建一个静态单例对象,然后返回单例对象的地址给外部即可。
class Singleton
{
public:static Singleton* GetInstance(){// 静态对象的初始化只会执行一次static Singleton _inst;return &_inst;}private:Singleton() {};Singleton(const Singleton&) = delete;Singleton& operator=(const Singleton&) = delete;
};
缺点:
- 单例对象创建在静态区,如果单例对象过大,存储在静态区不太合适
- 因为它在静态区,所以我们无法主动释放单例对象
四. 饿汉模式和懒汉模式对比
饿汉
- 优点:简单
- 缺点:
- 如果单例对象构造函数的工作较多,会导致程序启动慢,迟迟进不了入口 main 函数
- 如果系统中有多个单例对象,且它们之间有初始化的耦合关系,饿汉模式无法控制它们的初始化顺序
懒汉
- 优点:需要时才调用,可以达到延迟加载的效果
- 确定:相对于饿汉,实现起来更复杂,需要加锁和双检查
相关文章:

【C++】单例模式
文章目录 一. 介绍二. 饿汉模式三. 懒汉模式四. 饿汉模式和懒汉模式对比 一. 介绍 单例模式是属于设计模式的一种,那什么是设计模式呢? 设计模式(Design Pattern)是一套被反复使用、多数人知晓的、经过分类的、代码设计经验的总…...
【kubernetes】使用luakube访问kubernetes api
文章目录 1 kubernetes client2 luakube初体验3 luakube代码分析4 luakube包的调用5 lua相关5.1 self5.2 metatable5.2.1 使用metatable对table新增操作符5.2.2 使用metatable对table新增方法5.2.3 再探luakube 6 参考文档 1 kubernetes client 客户端列出了各种语言对应的访问…...

【算法分析与设计】贪心算法(下)
目录 一、单源最短路径1.1 算法基本思想1.2 算法设计思想1.3 算法的正确性和计算复杂性1.4 归纳证明思路1.5 归纳步骤证明 二、最小生成树2.1 最小生成树性质2.1.1 生成树的性质2.1.2 生成树性质的应用 2.2 Prim算法2.2.1 正确性证明2.2.2 归纳基础2.2.3 归纳步骤2.3 Kruskal算…...

Arm Cache学习资料大汇总
关键词:cache学习、mmu学习、cache资料、mmu资料、arm资料、armv8资料、armv9资料、 trustzone视频、tee视频、ATF视频、secureboot视频、安全启动视频、selinux视频,cache视频、mmu视频,armv8视频、armv9视频、FF-A视频、密码学视频、RME/CC…...
Docker 学习总结(79)—— Dockerfile 编写技巧总结
目标 更快的构建速度 更小的 Docker 镜像大小 更少的 Docker 镜像层 充分利用镜像缓存 增加 Dockerfile 可读性 让 Docker 容器使用起来更简单 总结 编写 .dockerignore 文件 容器只运行单个应用 将多个 RUN 指令合并为一个 基础镜像的标签不要用 latest 每个 RUN 指令后删除多…...

链表经典面试题(二)
返回中间结点 1.中间结点的题目2.中间结点的图文分析3.中间结点的基本代码4.中间结点的优化代码 1.中间结点的题目 2.中间结点的图文分析 方法1:先求整体长度,再除以2,所得到的就是中间结点 方法2:双指针法,快指针走两…...

89、Redis 的 value 所支持的数据类型(String、List、Set、Zset、Hash)---->Zset 相关命令
本次讲解要点: ** Set相关命令:是指value中的数据类型** 启动redis服务器: 打开小黑窗: C:\Users\JH>e: E:>cd E:\install\Redis6.0\Redis-x64-6.0.14\bin E:\install\Redis6.0\Redis-x64-6.0.14\bin>redis-server.exe …...

知识图谱02——使用python将信息录入neo4j
将文档传入chatgpt,生成对应的cypher语句 链接: https://pan.baidu.com/s/1Ny-ttbBSpqYEigwYiCWMeA?pwdc7sc 提取码: c7sc 使用命令行安装对应的包 pip install neo4jchatgpt生成出的txt文档中的内容如下: MERGE (Node1:Entity {name: 原始舱单提运单…...
greenDAO-Android轻量级快速ORM框架
官网 https://github.com/greenrobot/greenDAO 简介 greenDAO is a light & fast ORM for Android that maps objects to SQLite databases. Being highly optimized for Android, greenDAO offers great performance and consumes minimal memory. Home page, documen…...

结构型设计模式——组合模式
摘要 组合模式(composite pattern): 允许你将对象组合成树形结构来表现"整体/部分"层次结构. 组合能让客户以一致的方式处理个别对象以及对象组合。 一、组合模式的意图 将对象组合成树形结构来表示“整体/部分”层次关系,允许用户以相同的方式处理单独…...
40. 组合总和 II
给定一个候选人编号的集合 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。 candidates 中的每个数字在每个组合中只能使用 一次 。 注意:解集不能包含重复的组合。 示例 1: 输入: candidates [10,1,2,7,6,1,5…...

安卓玩机-----给app加注册码 app加弹窗 云注入弹窗
在对接很多工作室业务中有些客户需要在他们自带的有些app中加注册码或者验证码的需求。其实操作起来也很简单。很多反编译软件有自带的注入功能。例如注入弹窗。这个是需要对应的注册码来启动应用。而且是随机id。重新安装app后需要重新注册才可以继续使用,原则上可…...

NLP的不同研究领域和最新发展的概述
一、介绍 作为理解、生成和处理自然语言文本的有效方法,自然语言处理 (NLP) 的研究近年来迅速普及并被广泛采用。鉴于NLP的快速发展,获得该领域的概述和维护它是困难的。这篇博文旨在提供NLP不同研究领域的结构化概述,…...

1.物联网射频识别,RFID概念、组成、中间件、标准,全球物品编码——EPC码
1.RFID概念 RFID是Radio Frequency Identification的缩写,又称无线射频识别,是一种通信技术,可通过无线电讯号识别特定目标并读写相关数据,而无需与被识别物体建立机械或光学接触。 RFID(Radio Frequency Identificati…...
MySQL函数与控制结构
MySQL数据库管理系统在数据存储和检索方面发挥着重要作用。除了基础的数据操作外,MySQL还提供了丰富的函数和控制结构来进行更复杂的数据处理。 本文将详细介绍如何在MySQL中使用begin-end语句块、自定义函数、以及各种控制语句。通过《三国志》游戏数据的实例将更深入地了解…...

【论文极速读】Prompt Tuning——一种高效的LLM模型下游任务适配方式
【论文极速读】Prompt Tuning——一种高效的LLM模型下游任务适配方式 FesianXu 20230928 at Baidu Search Team 前言 Prompt Tuning是一种PEFT方法(Parameter-Efficient FineTune),旨在以高效的方式对LLM模型进行下游任务适配,本…...

如何在 Elasticsearch 中使用 Openai Embedding 进行语义搜索
随着强大的 GPT 模型的出现,文本的语义提取得到了改进。 在本文中,我们将使用嵌入向量在文档中进行搜索,而不是使用关键字进行老式搜索。 什么是嵌入 - embedding? 在深度学习术语中,嵌入是文本或图像等内容的数字表示…...

世界第一ERP厂商SAP,推出类ChatGPT产品—Joule
9月27日,世界排名第一ERP厂商SAP在官网宣布,推出生成式AI助手Joule,并将其集成在采购、供应链、销售、人力资源、营销、数据分析等产品矩阵中,帮助客户实现降本增效。 据悉,Joule是一款功能类似ChatGPT的产品…...

嵌入式Linux应用开发-基础知识-第十八章系统对中断的处理③
嵌入式Linux应用开发-基础知识-第十八章系统对中断的处理③ 第十八章 Linux系统对中断的处理 ③18.5 编写使用中断的按键驱动程序 ③18.5.1 编程思路18.5.1.1 设备树相关18.5.1.2 驱动代码相关 18.5.2 先编写驱动程序18.5.2.1 从设备树获得 GPIO18.5.2.2 从 GPIO获得中断号18.5…...

【Python】返回指定时间对应的时间戳
使用模块datetime,附赠一个没啥用的“时间推算”功能(获取n天后对应的时间 代码: import datetimedef GetTimestamp(year,month,day,hour,minute,second,*,relativeNone,timezoneNone):#返回指定时间戳。指定relative时进行时间推算"""根…...

UE5 学习系列(二)用户操作界面及介绍
这篇博客是 UE5 学习系列博客的第二篇,在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下: 【Note】:如果你已经完成安装等操作,可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作,重…...

第19节 Node.js Express 框架
Express 是一个为Node.js设计的web开发框架,它基于nodejs平台。 Express 简介 Express是一个简洁而灵活的node.js Web应用框架, 提供了一系列强大特性帮助你创建各种Web应用,和丰富的HTTP工具。 使用Express可以快速地搭建一个完整功能的网站。 Expre…...

Python爬虫(一):爬虫伪装
一、网站防爬机制概述 在当今互联网环境中,具有一定规模或盈利性质的网站几乎都实施了各种防爬措施。这些措施主要分为两大类: 身份验证机制:直接将未经授权的爬虫阻挡在外反爬技术体系:通过各种技术手段增加爬虫获取数据的难度…...

Ascend NPU上适配Step-Audio模型
1 概述 1.1 简述 Step-Audio 是业界首个集语音理解与生成控制一体化的产品级开源实时语音对话系统,支持多语言对话(如 中文,英文,日语),语音情感(如 开心,悲伤)&#x…...
精益数据分析(97/126):邮件营销与用户参与度的关键指标优化指南
精益数据分析(97/126):邮件营销与用户参与度的关键指标优化指南 在数字化营销时代,邮件列表效度、用户参与度和网站性能等指标往往决定着创业公司的增长成败。今天,我们将深入解析邮件打开率、网站可用性、页面参与时…...
CSS | transition 和 transform的用处和区别
省流总结: transform用于变换/变形,transition是动画控制器 transform 用来对元素进行变形,常见的操作如下,它是立即生效的样式变形属性。 旋转 rotate(角度deg)、平移 translateX(像素px)、缩放 scale(倍数)、倾斜 skewX(角度…...

R 语言科研绘图第 55 期 --- 网络图-聚类
在发表科研论文的过程中,科研绘图是必不可少的,一张好看的图形会是文章很大的加分项。 为了便于使用,本系列文章介绍的所有绘图都已收录到了 sciRplot 项目中,获取方式: R 语言科研绘图模板 --- sciRplothttps://mp.…...
第八部分:阶段项目 6:构建 React 前端应用
现在,是时候将你学到的 React 基础知识付诸实践,构建一个简单的前端应用来模拟与后端 API 的交互了。在这个阶段,你可以先使用模拟数据,或者如果你的后端 API(阶段项目 5)已经搭建好,可以直接连…...
【把数组变成一棵树】有序数组秒变平衡BST,原来可以这么优雅!
【把数组变成一棵树】有序数组秒变平衡BST,原来可以这么优雅! 🌱 前言:一棵树的浪漫,从数组开始说起 程序员的世界里,数组是最常见的基本结构之一,几乎每种语言、每种算法都少不了它。可你有没有想过,一组看似“线性排列”的有序数组,竟然可以**“长”成一棵平衡的二…...

Vue3 PC端 UI组件库我更推荐Naive UI
一、Vue3生态现状与UI库选择的重要性 随着Vue3的稳定发布和Composition API的广泛采用,前端开发者面临着UI组件库的重新选择。一个好的UI库不仅能提升开发效率,还能确保项目的长期可维护性。本文将对比三大主流Vue3 UI库(Naive UI、Element …...