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…...

SpringBoot-17-MyBatis动态SQL标签之常用标签
文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…...

汽车生产虚拟实训中的技能提升与生产优化
在制造业蓬勃发展的大背景下,虚拟教学实训宛如一颗璀璨的新星,正发挥着不可或缺且日益凸显的关键作用,源源不断地为企业的稳健前行与创新发展注入磅礴强大的动力。就以汽车制造企业这一极具代表性的行业主体为例,汽车生产线上各类…...

学习STC51单片机31(芯片为STC89C52RCRC)OLED显示屏1
每日一言 生活的美好,总是藏在那些你咬牙坚持的日子里。 硬件:OLED 以后要用到OLED的时候找到这个文件 OLED的设备地址 SSD1306"SSD" 是品牌缩写,"1306" 是产品编号。 驱动 OLED 屏幕的 IIC 总线数据传输格式 示意图 …...
python爬虫:Newspaper3k 的详细使用(好用的新闻网站文章抓取和解析的Python库)
更多内容请见: 爬虫和逆向教程-专栏介绍和目录 文章目录 一、Newspaper3k 概述1.1 Newspaper3k 介绍1.2 主要功能1.3 典型应用场景1.4 安装二、基本用法2.2 提取单篇文章的内容2.2 处理多篇文档三、高级选项3.1 自定义配置3.2 分析文章情感四、实战案例4.1 构建新闻摘要聚合器…...
WEB3全栈开发——面试专业技能点P2智能合约开发(Solidity)
一、Solidity合约开发 下面是 Solidity 合约开发 的概念、代码示例及讲解,适合用作学习或写简历项目背景说明。 🧠 一、概念简介:Solidity 合约开发 Solidity 是一种专门为 以太坊(Ethereum)平台编写智能合约的高级编…...
OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别
OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别 直接训练提示词嵌入向量的核心区别 您提到的代码: prompt_embedding = initial_embedding.clone().requires_grad_(True) optimizer = torch.optim.Adam([prompt_embedding...

用docker来安装部署freeswitch记录
今天刚才测试一个callcenter的项目,所以尝试安装freeswitch 1、使用轩辕镜像 - 中国开发者首选的专业 Docker 镜像加速服务平台 编辑下面/etc/docker/daemon.json文件为 {"registry-mirrors": ["https://docker.xuanyuan.me"] }同时可以进入轩…...
虚拟电厂发展三大趋势:市场化、技术主导、车网互联
市场化:从政策驱动到多元盈利 政策全面赋能 2025年4月,国家发改委、能源局发布《关于加快推进虚拟电厂发展的指导意见》,首次明确虚拟电厂为“独立市场主体”,提出硬性目标:2027年全国调节能力≥2000万千瓦࿰…...

uniapp 开发ios, xcode 提交app store connect 和 testflight内测
uniapp 中配置 配置manifest 文档:manifest.json 应用配置 | uni-app官网 hbuilderx中本地打包 下载IOS最新SDK 开发环境 | uni小程序SDK hbulderx 版本号:4.66 对应的sdk版本 4.66 两者必须一致 本地打包的资源导入到SDK 导入资源 | uni小程序SDK …...
为什么要创建 Vue 实例
核心原因:Vue 需要一个「控制中心」来驱动整个应用 你可以把 Vue 实例想象成你应用的**「大脑」或「引擎」。它负责协调模板、数据、逻辑和行为,将它们变成一个活的、可交互的应用**。没有这个实例,你的代码只是一堆静态的 HTML、JavaScript 变量和函数,无法「活」起来。 …...