C++ 单例模式(介绍+实现)
文章目录
- 一. 设计模式
- 二. 单例模式
- 三. 饿汉模式
- 四. 懒汉模式
- 结束语
一. 设计模式
单例模式是一种设计模式
设计模式(Design Pattern)是一套被反复使用,多数人知晓的,经过分类的,代码设计经验的总结。
为什么要有设计模式
就像人类历史发展会产生兵法,最开始部落之间打仗都是谁人多谁获胜。但后来春秋战国时期,七国之间经常战争,发现战争也是有套路的,后来孙子就总结了《孙子兵法》。设计模式也是如此。
设计模式可以提高代码的可重用性,让代码更容易被他人理解,保证代码可靠性。设计模式使代码编写真正工程化;设计模式是软件工程的基石脉络,如同大厦的结构一般
二. 单例模式
一个类只能创建一个对象,即单例模式,该模式可以保证系统重该类只有一个实例,并提供一个访问它的全局访问点,该实例被所有程序模块共享。
比如在某个服务器程序中,该服务器的配置信息存放在一个文件中,这些配置数据由一个单例对象统一读取,然后服务进程中的其他对象再通过这个单例对象获取这些配置信息,这种方式简化了在复杂环境下的配置管理
单例模式有两种实现方式:饿汉模式&懒汉模式
三. 饿汉模式
饿汉模式,是在最开始就创建对象,即main函数开始前,对象就已经存在
要点有以下几个:
- 因为全局只能有一个对象,所以需要将构造函数私有化
- 内部封装static静态对象指针,然后类外初始化
- 提供静态成员函数,返回静态对象指针
- 使用互斥锁保证数据读取的线程安全
//饿汉模式
//在main函数调用前对象就存在
class Singleton
{
public://静态成员变量获取对象指针static Singleton*GetInstance(){return _ins;}//添加数据void Add(const char*str){_vmtx.lock();_v.push_back(str);_vmtx.unlock();}//打印数据void Print(){_vmtx.lock();for (auto& e : _v){cout << e << endl;}_vmtx.unlock();}private://构造函数私有化Singleton(){}
private:vector<string> _v;//存储数据mutex _vmtx;//互斥锁static Singleton*_ins;//静态指针
};//静态成员变量类外初始化
Singleton* Singleton::_ins = new Singleton();
饿汉模式的优点就是相对于懒汉模式,较为简单
缺点是,程序刚开始时就创建,如果对象较大,可能导致进程启动慢,且如果有多个单例类对象实例启动顺序不确定
如果这个单例对象在多线程并发环境下频繁使用,性能要求较高,那么显然使用饿汉模式来避免资源竞争,提高响应速度更好
四. 懒汉模式
懒汉模式是在第一次使用实例对象时,才创建对象
如果单例对象构造十分耗时或者占用很多资源,比如加载插件,初始化网络连接,读取文件等,为了不影响程序启动,可以使用懒汉模式(延迟加载)
简易的懒汉模式
class Singleton
{
public://静态成员变量获取对象指针static Singleton*GetInstance(){static Singleton _ins;return &_ins;}//添加数据void Add(const char*str){_vmtx.lock();_v.push_back(str);_vmtx.unlock();}//打印数据void Print(){_vmtx.lock();for (auto& e : _v){cout << e << endl;}_vmtx.unlock();}private://构造函数私有化Singleton(){}
private:vector<string> _v;//存储数据mutex _vmtx;//互斥锁
};
但
stactic对象在C++11前无法保证线程安全,C++11后保证static对象初始化时线程安全的
复杂的懒汉模式
要点有如下几个:
- 懒汉模式的GetInstance需要有双检查加锁,同时因为是静态成员函数,所以还需要封装一个静态的互斥锁保护
- 可以使用DelInstance显示释放,但也可以通过
回收机制在程序结束时回收资源。
做法是内部定义一个类,该类的析构函数会显示调用DelInstance,然后再定义一个全局的回收机制对象,这样程序结束时会自动销毁回收机制对象,同时调用DelInstance
//懒汉模式
//第一次调用GetInstance才有对象
class Singleton
{
public://静态成员变量获取对象指针static Singleton*GetInstance(){//双检查加锁if (_ins == nullptr)//提高效率{_imtx.lock();//第一次调用为空才初始化if (_ins == nullptr)//线程安全{_ins = new Singleton();}_imtx.unlock();}return _ins;}//添加数据void Add(const char*str){_vmtx.lock();_v.push_back(str);_vmtx.unlock();}//打印数据void Print(){_vmtx.lock();for (auto& e : _v){cout << e << endl;}_vmtx.unlock();}//销毁static void DelInstance(){_imtx.lock();if (_ins){delete _ins;_ins = nullptr;}_imtx.unlock();}//回收机制class GC{public:~GC(){DelInstance();}};static GC _gc;//声明
private://构造函数私有化Singleton(){}
private:vector<string> _v;//存储数据mutex _vmtx;//保护vector的互斥锁static Singleton*_ins;//静态指针static mutex _imtx;//保护Singleton初始化的互斥锁
};//静态成员变量类外初始化为空
Singleton* Singleton::_ins = nullptr;
mutex Singleton::_imtx;//程序结束时,会调用其析构函数,内部再调用DelInstance()
Singleton::GC Singleton::_gc;//定义
结束语
感谢你的阅读
如果觉得本篇文章对你有所帮助的话,不妨点个赞支持一下博主,拜托啦,这对我真的很重要。

相关文章:
C++ 单例模式(介绍+实现)
文章目录 一. 设计模式二. 单例模式三. 饿汉模式四. 懒汉模式结束语 一. 设计模式 单例模式是一种设计模式 设计模式(Design Pattern)是一套被反复使用,多数人知晓的,经过分类的,代码设计经验的总结。 为什么要有设计模式 就像人类历史发展会…...
uniapp项目集成本地插件
在项目根目录下创建nativeplugins文件夹 拷贝插件到目录nativeplugins 在manifest.json -> App原生插件配置 -> 本地插件里勾选插件 删除本地基座和手机app从新自定义基座运行...
MFC CList 类的使用
MFC提供CList 类; 类CList支持可按顺序或按值访问的非唯一对象的有序列表;CList 列表与双链接列表行为相似; 类型POSITION的变量是列表的关键字;可使用POSITION变量作为循环因子来顺序遍历列表,作为书签来保存位置&am…...
iptable防火墙
防火墙 防火墙的主要功能是隔离,决定数据是否可以被外网访问以及哪些数据可以进入内。 它主要部署在网络边缘或者主机边缘,应用在网络层。 防火墙的安全技术: 1、入侵检测系统:检测数威胁,病毒,木马,不…...
二、SQL-5.DQL-9).执行顺序
一、案例: 查询年龄大于15的员工的姓名、年龄,并根据年龄进行升序排序 select name, age from emp where age > 15 order by age asc; 先执行①from(定义emp的别名为e),再执行②where(调用别名e&…...
Ubuntu通用镜像加速配置
备份 cp -rf /etc/apt/sources.list /etc/apt/sources.list.bak开始配置 阿里云 sed -i shttp://archive.ubuntu.comhttps://mirrors.aliyun.comg /etc/apt/sources.listsed -i shttp://security.ubuntu.comhttps://mirrors.aliyun.comg /etc/apt/sources.list清华源 sed -i …...
Linux安装部署Nacos和sentinel
1.将nacos安装包下载到本地后上传到linux中 2.进入nacos的/bin目录,输入命令启动nacos [rootlocalhost bin]# sh startup.sh -m standalone注:使用第二种方式启动,同时增加日志记录的功能 2.2 startup.sh文件是不具备足够的权限,否则不能操作 给文件赋予执行权限 [rootlocalh…...
Vue3+ElementPlus+TS实现右上角消息数量实时更新
Vue3ElementPlusTS实现右上角消息数量实时更新 背景 项目需求,前端右上角铃铛图标 显示接收到的消息通知,并且显示消息数量以及实时更新。(一般是点击操作按钮后增加一条消息通知,图标上的数字也随之更新) 【原来的想…...
去除重复字母(力扣)贪心 + 队列 JAVA
给你一个字符串 s ,请你去除字符串中重复的字母,使得每个字母只出现一次。需保证 返回结果的字典序最小(要求不能打乱其他字符的相对位置)。 示例 1: 输入:s “bcabc” 输出:“abc” 示例 2&am…...
Spring,SpringBoot,Spring MVC的区别是什么
1.Spring是什么 我们通常所说的 Spring 指的是 Spring Framework(Spring 框架),它是⼀个开源框架,有着活跃⽽庞⼤的社区,这就是它之所以能⻓久不衰的原因。Spring ⽀持⼴泛的应⽤场景,它可以让 Java 企业级…...
在CSDN学Golang云原生(Docker镜像)
一,镜像分层机制 在 Docker 中,一个镜像可以由多个分层(Layer)组成。每个分层都表示一些修改或添加到上一个分层的文件系统差异。 Golang 在构建 Docker 镜像时也支持类似的机制,通过 docker build 命令来创建一个包…...
Hive窗口函数大全
Hive窗口函数 一、偏移量函数laglead 二、窗口分析函数first_valuelast_value 三、排序函数rankdense_rankrow_number 一、偏移量函数 lag 语法:lag(col,n,default_val) 返回值:字段类型 说明:往前第n行数据。 lag(column字段,第…...
达闼面试(部分)(未完全解析)
grpc怎么解决负载均衡问题? Answer by newBing : gRPC提供了多种负载均衡策略,包括轮询、随机、最少连接数等。gRPC客户端可以使用这些策略来选择要连接的服务器。 k8s环境下部署grpc的几种方案 : 在k8s环境中,可以选择headless service,或者…...
Makefile常用函数
目录 字符串替换函数:subst 模式字符串替换函数:patsubst 去空格函数 strip 查找字符串函数 findstring 过滤函数 filter 反过滤函数 filter-out 排序函数 sort 取目录函数 dir 取文件函数 notdir 取后缀函数 suffix 取前缀函数 basename 加…...
mysql的一些知识整理
这里整理一些mysql相关的知识点,是自己不太熟悉的内容 varchar(n) 中 n 最大取值为多少 MySQL 规定除了 TEXT、BLOBs 这种大对象类型之外,其他所有的列(不包括隐藏列和记录头信息)占用的字节长度加起来不能超过 65535 个字节。 …...
修改密码和再次确认密码的js和element-ui的使用
<template><div><!-- plan的插槽 --><plan title"修改密码"><!-- 插槽的名字 --><span slot"header">修改密码</span><el-form:model"ruleForm2"status-icon:rules"rules2"ref"rul…...
蓝桥杯专题-真题版含答案-【垒骰子_动态规划】【抽签】【平方怪圈】【凑算式】
点击跳转专栏>Unity3D特效百例点击跳转专栏>案例项目实战源码点击跳转专栏>游戏脚本-辅助自动化点击跳转专栏>Android控件全解手册点击跳转专栏>Scratch编程案例点击跳转>软考全系列点击跳转>蓝桥系列 👉关于作者 专注于Android/Unity和各种游…...
kubernetes调试利器——kubectl debug工具
通常情况下,业务容器所使用的镜像是非常精简的,而一旦业务容器出现问题,通过kubectl exec进入到容器时,我们会发现自己需要使用的工具都没有,也无法通过apt, apt-get, yum等包管理工具下载需要的工具。 想要解决这个尴…...
浅谈es5如何保证并发请求的返回顺序
最近在公司实习写的是es5,在和回调地狱经过一番拉扯之后写下这篇文章,也算是体验了一把没有promise的时代 假设我们的div有一个日历列表,但是由于大小关系只能每次显示2天的信息,项目限制只能使用es5,不能使用es6的pro…...
深入浅出Pytorch函数——torch.squeeze
分类目录:《深入浅出Pytorch函数》总目录 相关文章: 深入浅出Pytorch函数——torch.squeeze 深入浅出Pytorch函数——torch.unsqueeze 将输入张量形状为1的维度去除并返回。比如输入向量的形状为 A 1 B 1 C 1 D A\times1\times B\times1\times C…...
设计模式和设计原则回顾
设计模式和设计原则回顾 23种设计模式是设计原则的完美体现,设计原则设计原则是设计模式的理论基石, 设计模式 在经典的设计模式分类中(如《设计模式:可复用面向对象软件的基础》一书中),总共有23种设计模式,分为三大类: 一、创建型模式(5种) 1. 单例模式(Sing…...
最新SpringBoot+SpringCloud+Nacos微服务框架分享
文章目录 前言一、服务规划二、架构核心1.cloud的pom2.gateway的异常handler3.gateway的filter4、admin的pom5、admin的登录核心 三、code-helper分享总结 前言 最近有个活蛮赶的,根据Excel列的需求预估的工时直接打骨折,不要问我为什么,主要…...
mysql已经安装,但是通过rpm -q 没有找mysql相关的已安装包
文章目录 现象:mysql已经安装,但是通过rpm -q 没有找mysql相关的已安装包遇到 rpm 命令找不到已经安装的 MySQL 包时,可能是因为以下几个原因:1.MySQL 不是通过 RPM 包安装的2.RPM 数据库损坏3.使用了不同的包名或路径4.使用其他包…...
Unsafe Fileupload篇补充-木马的详细教程与木马分享(中国蚁剑方式)
在之前的皮卡丘靶场第九期Unsafe Fileupload篇中我们学习了木马的原理并且学了一个简单的木马文件 本期内容是为了更好的为大家解释木马(服务器方面的)的原理,连接,以及各种木马及连接工具的分享 文件木马:https://w…...
Pinocchio 库详解及其在足式机器人上的应用
Pinocchio 库详解及其在足式机器人上的应用 Pinocchio (Pinocchio is not only a nose) 是一个开源的 C 库,专门用于快速计算机器人模型的正向运动学、逆向运动学、雅可比矩阵、动力学和动力学导数。它主要关注效率和准确性,并提供了一个通用的框架&…...
安卓基础(aar)
重新设置java21的环境,临时设置 $env:JAVA_HOME "D:\Android Studio\jbr" 查看当前环境变量 JAVA_HOME 的值 echo $env:JAVA_HOME 构建ARR文件 ./gradlew :private-lib:assembleRelease 目录是这样的: MyApp/ ├── app/ …...
IP如何挑?2025年海外专线IP如何购买?
你花了时间和预算买了IP,结果IP质量不佳,项目效率低下不说,还可能带来莫名的网络问题,是不是太闹心了?尤其是在面对海外专线IP时,到底怎么才能买到适合自己的呢?所以,挑IP绝对是个技…...
推荐 github 项目:GeminiImageApp(图片生成方向,可以做一定的素材)
推荐 github 项目:GeminiImageApp(图片生成方向,可以做一定的素材) 这个项目能干嘛? 使用 gemini 2.0 的 api 和 google 其他的 api 来做衍生处理 简化和优化了文生图和图生图的行为(我的最主要) 并且有一些目标检测和切割(我用不到) 视频和 imagefx 因为没 a…...
RSS 2025|从说明书学习复杂机器人操作任务:NUS邵林团队提出全新机器人装配技能学习框架Manual2Skill
视觉语言模型(Vision-Language Models, VLMs),为真实环境中的机器人操作任务提供了极具潜力的解决方案。 尽管 VLMs 取得了显著进展,机器人仍难以胜任复杂的长时程任务(如家具装配),主要受限于人…...
淘宝扭蛋机小程序系统开发:打造互动性强的购物平台
淘宝扭蛋机小程序系统的开发,旨在打造一个互动性强的购物平台,让用户在购物的同时,能够享受到更多的乐趣和惊喜。 淘宝扭蛋机小程序系统拥有丰富的互动功能。用户可以通过虚拟摇杆操作扭蛋机,实现旋转、抽拉等动作,增…...
