【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 函数
    • 如果系统中有多个单例对象,且它们之间有初始化的耦合关系,饿汉模式无法控制它们的初始化顺序

懒汉

  • 优点:需要时才调用,可以达到延迟加载的效果
  • 确定:相对于饿汉,实现起来更复杂,需要加锁和双检查

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

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

相关文章

从MVC到DDD,该如何下手重构?

作者:付政委 博客:bugstack.cn 沉淀、分享、成长,让自己和他人都能有所收获!😄 大家好,我是技术UP主小傅哥。多年的 DDD 应用,使我开了技术的眼界! MVC 旧工程腐化严重,…

【嵌入式】使用MultiButton开源库驱动按键并控制多级界面切换

目录 一 背景说明 二 参考资料 三 MultiButton开源库移植 四 设计实现--驱动按键 五 设计实现--界面处理 一 背景说明 需要做一个通过不同按键控制多级界面切换以及界面动作的程序。 查阅相关资料,发现网上大多数的应用都比较繁琐,且对于多级界面的…

ahk系列——ahk_v2实现win10任意界面ocr

前言: 不依赖外部api接口,界面简洁,翻译快速,操作简单, 有网络就能用 、还可以把ocr结果非中文翻译成中文、同样可以识别中英日韩等60多个国家语言并翻译成中文,十分的nice 1、所需环境 windows10及其以上…

软件设计师_数据库系统_学习笔记

文章目录 3.1 数据库模式3.1.1 三级模式 两级映射3.1.2 数据库设计过程 3.2 ER模型3.3 关系代数与元组演算3.4 规范化理论3.5 并发控制3.6 数据库完整性约束3.7 分布式数据库3.8 数据仓库与数据挖掘 3.1 数据库模式 3.1.1 三级模式 两级映射 内模式直接与物理数据库相关联的 定…

如何初始化一个vue项目

如何初始化一个vue项目 安装 vue-cli 后 ,终端执行 vue ui npm install vue-cli --save-devCLI 服务 | Vue CLI (vuejs.org) 等一段时间后 。。。 进入项目仪表盘 设置其他模块 项目构建后目录 vue.config.js 文件相关配置 官方vue.config.js 参考文档 https://cli.vuejs.o…

嵌入式Linux应用开发-基础知识-第十八章系统对中断的处理②

嵌入式Linux应用开发-基础知识-第十八章系统对中断的处理② 第十八章 Linux系统对中断的处理 ②18.3 Linux中断系统中的重要数据结构18.3.1 irq_desc数组18.3.2 irqaction结构体18.3.3 irq_data结构体18.3.4 irq_domain结构体18.3.5 irq_chip结构体 18.4 在设备树中指定中断_在…

区块链(8):p2p去中心化之websoket服务端实现业务逻辑

1 业务逻辑 例如 peer1和peer2之间相互通信 peer1通过onopen{ write(Mesage(QUERY_LATEST))} 向peer2发送消息“我要最新的区块”。 peer2通过onMessage收到消息,通过handleMessage方法对消息进行处理。 handleMessage根据消息类型进行处理 RESPONSE_BLOCKCHAIN:返回区块链…

基于Java的游戏检索系统设计与实现(源码+lw+部署文档+讲解等)

文章目录 前言用户功能已注册用户的功能后台功能管理员功能具体实现截图论文参考详细视频演示为什么选择我自己的网站自己的小程序(小蔡coding)有保障的售后福利 代码参考源码获取 前言 💗博主介绍:✌全网粉丝10W,CSDN特邀作者、博…

BI神器Power Query(25)-- 使用PQ实现表格多列转换(1/3)

实例需求:原始表格包含多列属性数据,现在需要将不同属性分列展示在不同的行中,att1、att3、att5为一组,att2、att3、att6为另一组,数据如下所示。 更新表格数据 原始数据表: Col1Col2Att1Att2Att3Att4Att5Att6AAADD…

嵌入式Linux应用开发-基础知识-第十八章系统对中断的处理①

嵌入式Linux应用开发-基础知识-第十八章系统对中断的处理 第十八章 Linux 系统对中断的处理①18.1 进程、线程、中断的核心:栈18.1.1 ARM 处理器程序运行的过程18.1.2 程序被中断时,怎么保存现场18.1.3 进程、线程的概念 18.2 Linux系统对中断处理的演进…

【教学类-36-10】20230908方脸爷爷和圆脸奶奶(midjounery-niji)(中班:《我爱我家》数:连线、涂色)

背景需求: 领导们鼓动我去参加上海市高级职称评审(科研成果比较多),为下一轮保教主任评高级“探探路”。虽然自我感觉道行浅薄,无缘高级,但领导给机会,自然要参与一下,努力了解整个…

【Python】返回指定时间对应的时间戳

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

架构师习题--嵌入式习题

架构师习题--嵌入式习题 可靠度:是单个系统的可靠性 避错和容错 N版本程序设计是静态 恢复块是动态 恢复块是主机坏了调用备用机,每次只有单机运行 N版本是N机器同时运行 恢复块是主机坏了调用备用机,后向恢复到之前的状态 N版主直接向前走

Purism 推出注重隐私的 Linux 平板电脑

导读一款昂贵的 Linux 平板电脑,注重安全和隐私。让我们拭目以待。 Purism 是一家日益流行的计算机硬件产品制造商,专门提供配备注重隐私的开源 Linux 发行版的笔记本电脑、台式机和移动设备。 最近,他们发布了一款新产品 Librem 11 平板电…

SmartX 边缘计算解决方案:简单稳定,支持各类应用负载

在《一文了解近端边缘 IT 基础架构技术需求》文章中,我们为大家分析了边缘应用对 IT 基础架构的技术要求,以及为什么超融合架构是支持边缘场景的最佳选择。值得一提的是,IDC 近日发布的《中国软件定义存储(SDS)及超融合…

Centos7配置firewalld防火墙规则

这里写自定义目录标题 欢迎使用Markdown编辑器一、简单介绍二、特点和功能2.1、区域(Zone)2.2、运行时和永久配置2.3、服务和端口2.4、动态更新2.5、连接跟踪2.6、D-Bus接口 三、设置规则3.1、启动防火墙服务3.2、新建防火墙规则的服务,添加端…

objective-c 基础学习

目录 第一节:OC 介绍 ​​第二节:Fundation 框架 ​第三节:NSLog 相对于print 的增强 ​第四节:NSString ​第五节:oc新增数据类型 第六节: 类和对象 ​类的方法的声明与实现 ​第七节:类…

多叉树+图实现简单业务流程

文章目录 场景整体架构流程业务界面技术细节小结 场景 这次遇到一个需求,大致就是任务组织成方案,方案组织成预案,预案可裁剪调整.预案关联事件等级配置,告警触发预案产生事件.然后任务执行是有先后的,也就是有流程概念. 整体架构流程 方案管理、预案管理构成任务流程的基础条…

28 drf-Vue个人向总结-1

文章目录 前后端分离开发展示项目项补充知识开发问题浏览器解决跨域问题 drf 小tips设置资源root目录使用自定义的user表设置资源路径media数据库补充删除表中数据单页面与多页面模式过滤多层自关联后端提交的数据到底是什么jwt token登录设置普通的 token 原理使用流程解析 jw…

Day_17> 动态内存管理

目录 1.为什么存在动态内存分配? 2.动态内存函数的介绍 malloc calloc realloc 3.常见的动态内存错误 1.对NULL指针的解引用操作 2.对动态开辟空间的越界访问 3.对非动态开辟内存使用free释放 4.使用free释放一块动态开辟内存的一部分 5.对同一块动态内…