【C++基础】单例模式

本文章参考:单例模式 - 巴基速递 | 爱编程的大丙

什么是单例模式

在一个项目中,全局范围内,某个类的实例有且仅有一个,通过这个唯一实例向其他模块提供数据的全局访问,这种模式就叫单例模式。单例模式的典型应用就是任务队列。

如果使用单例模式,首先要保证这个类的实例有且仅有一个。因此,就必须采取一系列的防护措施。涉及一个类多对象操作的函数有以下几个:

构造函数:创建一个新的对象
拷贝构造函数:根据已有对象拷贝出一个新的对象
拷贝赋值操作符重载函数:两个对象之间的赋值

解决措施如下:

构造函数私有化,在类内部只调用一次
拷贝构造函数私有化或者禁用(使用 = delete)
拷贝赋值操作符重载函数私有化或者禁用

由于使用者在类外部不能使用构造函数,所以在类内部创建的这个唯一的对象必须是静态的,这样就可以通过类名来访问了,为了不破坏类的封装,我们都会把这个静态对象的访问权限设置为私有的。
在类中只有它的静态成员函数才能访问其静态成员变量,所以可以给这个单例类提供一个静态函数用于得到这个静态的单例对象。

饿汉模式

饿汉模式就是在类加载的时候立刻进行实例化,这样就得到了一个唯一的可用对象

class Singleton
{
public:Singleton(const Singleton& obj) = delete;  //禁止拷贝构造Singleton& operator=(const Singleton& obj) = delete;   //禁止运算符重载static Singleton* getInstance(){return m_obj;}
private:Singleton() = default;  //默认构造函数为私有static Singleton* m_obj;
};Singleton* Singleton::m_obj = new Singleton;int main()
{Singleton* m_obj = Singleton::getInstance();
}

注意:类的静态成员变量在使用之前必须在类的外部进行初始化才能使用

饿汉模式优点简单、线程安全,但其缺点是可能会浪费一些系统资源(单例对象在应用程序启动时就被创建,即使在某些情况下可能永远不会被使用),不支持延迟加载,不适用于需要根据运行时条件来创建单例对象的情况

懒汉模式

懒汉模式是在类加载的时候不去创建这个唯一的实例,而是在需要使用的时候再进行实例化。

class LazySingleton
{
public:LazySingleton(const LazySingleton& obj) = delete;  //禁止拷贝构造LazySingleton& operator=(const LazySingleton& obj) = delete;   //禁止运算符重载static LazySingleton* getInstance(){if (m_obj == nullptr)   m_obj = new LazySingleton;return m_obj;}private:LazySingleton() = default;  //默认构造函数为私有static  LazySingleton* m_obj;
};LazySingleton* LazySingleton::m_obj = nullptr;

采用懒汉模式时,在调用getInstance()函数获取单例对象的时候,如果在单线程情况下是没有什么问题的,如果是多个线程,调用这个函数去访问单例对象就有问题了。假设有三个线程同时执行了getInstance()函数,在这个函数内部每个线程都会new出一个实例对象。此时,这个任务队列类的实例对象不是一个而是3个,很显然这与单例模式的定义是相悖的。

故其懒汉模式存在线程安全问题

懒汉模式的线程安全问题

双重检查锁定方法

最常用的解决方案就是使用互斥锁。可以将创建单例对象的代码使用互斥锁锁住。

并且在加锁、解锁的代码块外层添加了一个if判断,
其中外层if判断的目的:
这样当任务队列的实例被创建出来之后,访问这个对象的线程就不会再执行加锁和解锁操作了
内层的if判断的目的
对于第一次创建单例对象的时候线程之间还是具有竞争关系

class LazySingleton
{
public:LazySingleton(const LazySingleton& obj) = delete;  //禁止拷贝构造LazySingleton& operator=(const LazySingleton& obj) = delete;   //禁止运算符重载static LazySingleton* getInstance(){if (m_obj == nullptr) {std::lock_guard<std::mutex> lock(m_mutex);  //加锁if (m_obj == nullptr)m_obj = new LazySingleton;}return m_obj;}private:LazySingleton() = default;  //默认构造函数为私有static  LazySingleton* m_obj;static std::mutex m_mutex;
};LazySingleton* LazySingleton::m_obj = nullptr;

静态局部对象

C++11保证了局部静态变量的初始化在多线程环境中是线程安全的。这是一个简单且安全的单例模式实现方式。 

class LazySingleton
{
public:LazySingleton(const LazySingleton& obj) = delete;  //禁止拷贝构造LazySingleton& operator=(const LazySingleton& obj) = delete;   //禁止运算符重载static LazySingleton* getInstance(){static LazySingleton m_obj;            return m_obj;}private:LazySingleton() = default;  //默认构造函数为私有
};

懒汉模式的缺点是在创建实例对象的时候有安全问题,但这样可以减少内存的浪费(如果用不到就不去申请内存了)。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[刷题记录]牛客面试笔刷TOP101

牛客笔试算法必刷TOP101系列,每日更新中~(主要是记录自己的刷题,所以描述的可能不是很清楚 但如果刚好能帮助到你就更好了) 后续后头复习的时候,记得是看正解啊,别对着错的例子傻傻看了... 目录 1.合并有序链表2023.9.3 2.链表是否有环2023.9.4 3.判断链表中环的入口点 …

Java基础学习笔记-4

前言 本学习笔记将介绍Java中的数组概念以及各种与数组相关的操作和示例代码。 Java基础学习笔记-1 Java基础学习笔记-2 Java基础学习笔记-3 Demo01 - 声明和初始化数组 public class Demo01 {public static void main(String[] args) {// 声明一个数组&#xff0c;指明了里…

一分钟图情论文:《原始的布拉德福定律》

天津大学图书馆的研究馆员范铮先生&#xff0c;在《图书情报工作》第一期中发表了题为《原始的布拉德福定律》的文章&#xff0c;详细介绍了布拉德福定律的历史背景、调查统计数据、文献曲线以及理论推导等关键内容。这篇文章让我们能够深入了解布拉德福定律的本质和原始构想。…

概率论与数理统计学习笔记(7)——全概率公式与贝叶斯公式

目录 1. 背景2. 全概率公式3. 贝叶斯公式 1. 背景 下图是本文的背景内容&#xff0c;小B休闲时间有80%的概率玩手机游戏&#xff0c;有20%的概率玩电脑游戏。这两个游戏都有抽卡环节&#xff0c;其中手游抽到金卡的概率为5%&#xff0c;端游抽到金卡的概率为15%。已知小B这天抽…

Windows环境下Springboot3+Graalvm+Idea 打包成原生镜像 踩坑

https://github.com/oracle/graal/https://github.com/graalvm/graalvm-ce-builds/releases/对应关系graalvm-ce-java17-windows-amd64-X.X.X.zipnative-image-installable-svm-java17-windows-amd64-X.X.X.jar本人使用:graalvm-ce-java17-windows-amd64-23.0.1.zipnative-imag…

蓝桥杯官网练习题(纸牌三角形)

题目描述 本题为填空题&#xff0c;只需要算出结果后&#xff0c;在代码中使用输出语句将所填结果输出即可。 A,2,3,4,5,6,7,8,9 共 99 张纸牌排成一个正三角形&#xff08;A 按 1 计算&#xff09;。要求每个边的和相等。 下图就是一种排法。 这样的排法可能会有很多。 如果…

JavaScript 设计模式 – 通过示例进行解释

大家好&#xff01;在本文中&#xff0c;我将解释什么是设计模式以及它们为何有用。 目录 什么是设计模式&#xff1f; 创意设计模式 单例模式 工厂方法模式 抽象工厂模式 建造者模式 原型模式 结构设计模式 适配器模式 装饰模式 立面图案 代理模式 行为设计模式 责任链模式 迭…

PostgreSQL docker compose安装配置

docker-compose.yml如下&#xff1a; version: 3services:postgres:image: postgres:15.4healthcheck:test: [ "CMD", "pg_isready", "-q", "-d", "postgres", "-U", "root" ]timeout: 45sinterval: 1…

修改Docker镜像默认下载地址

1、安装完docker desktop后&#xff0c;先不要打开 2、新建目录 D:\ProgramData\Docker 3、在C:\Users\你的用户名\AppData\Local下&#xff0c;打开cmd或者powershell执行以下命令&#xff0c;命令语法略有不同。 powershell命令&#xff1a; cmd /c mklink /J Docker D:\Pro…

1-5 AUTOSAR数据交换文件ARXML

目录 一、Arxml文件 二、各类ARXML文件 一、Arxml文件 arxml文件是AUTOSAR&#xff08;Automotive Open System Architecture&#xff09;标准定义的XML文件&#xff0c;用于描述汽车电子系统中的软件组件、通信接口和参数配置等信息。 arxml文件的主要作用是在AUTOSAR架构下…

golang教程 beego框架笔记一

安装beego 安装bee工具 beego文档 # windos 推荐使用 go install github.com/beego/bee/v2master go get -u github.com/beego/bee/v2masterwindows使用安装bee工具时碰到的问题&#xff1b; 环境配置都没有问题&#xff0c;但是执行官网的命令&#xff1a;go get -u github…

打造高效的私密论坛网站:Cpolar内网穿透+HadSky轻量级搭建指南

文章目录 前言1. 网站搭建1.1 网页下载和安装1.2 网页测试1.3 cpolar的安装和注册 2. 本地网页发布2.1 Cpolar临时数据隧道2.2 Cpolar稳定隧道&#xff08;云端设置&#xff09;2.3 Cpolar稳定隧道&#xff08;本地设置&#xff09;2.4 公网访问测试 总结 前言 经过多年的基础…

大数据和数据要素有什么关系?

大数据与数据要素之间存在密切的关系。大数据是指海量、多样化、高速生成的数据&#xff0c;而数据要素是指构成数据的基本元素或属性。数据要素包括但不限于数据的类型、结构、格式、单位、精度等。 大数据的产生和应用离不开数据要素的支持。数据要素确定了数据的基本特征和…

【网络基础】——HTTPS

目录 HTTPS背景知识 HTTPS是什么&#xff1f; 加密解密 为什么要加密 常见的加密方式 对称加密 非对称加密 数据摘要&&数据指纹 数字签名 HTTPS工作过程探究 方案1&#xff1a;只使用对称加密 方案2&#xff1a;只使用非对称加密 方案3&#xff1a;双方…

3分钟看懂NPDP| 超全版

NPDP考试是由美国产品开发与管理协会(PDMA)发起的产品经理国际资格认证考试&#xff0c;在中国国内由外专局培训中心举办考试&#xff0c;考生在报名参加NPDP考试前&#xff0c;需要了解NPDP&#xff0c;下面为大家详细介绍&#xff0c;供大家参考。 什么是NPDP? 产品经理国际…

RabbitMQ实现数据库与ElasticSearch的数据同步和分享文件过期处理

&#x1f388; 1 参考文档 RabbitMQ实现数据库与ElasticSearch的数据同步 | Hannya。-CSDN 企业级开发项目实战——基于RabbitMQ实现数据库、elasticsearch的数据同步 | 波总说先赚它一个小目标-CSDN SPringBoot集成RabbitMQ实现30秒过期删除功能 | 军大君-CSDN &#x1f50d; …

conda和Python的虚拟环境如何结合使用,以及二者之间到底有什么区别?

问题描述 今天在复现streamlit的代码时&#xff08;参考Streamlit 讲解专栏&#xff08;一&#xff09;&#xff1a;安装以及初步应用&#xff09;&#xff0c;根据这篇博文指导&#xff0c;要先用以下指令创建一个虚拟环境&#xff1a; # 创建虚拟环境&#xff08;使用venv&a…

【python】读取.dat格式文件

import binascii# 打开二进制文件以只读二进制模式 with open(EXCEL/文件.dat, rb) as file:binary_data file.read()print(binary_data)# 将二进制数据转换为十六进制字符串 hex_data binascii.hexlify(binary_data).decode(utf-8) # binary_data 现在包含了文件的二进制内容…

git标签基础

打标签:git可以给仓库历史中某个提交打上标签,以示重要,比较有代表人们会使用这个功能来标记发布结点(V1.0,V2.0) 列出本地标签: git tag --list git tag -l "V1.85*" 列出远端仓库的中所有标签 git ls-remote --tags给标签添加一些描述信息 git tag -a v1.3 -m …

热释电矢量传感器设计

1 概述 使用4个热释电传感器组成一个2X2的矩阵。通过曲线的相位差、 峰峰值等特征量来计算相关信息。本文使用STM32单片机设计、制作了热释电传感器矩阵&#xff1b;使用C#.NET设计了上位机软件。为以上研究做了试验平台。 2 硬件电路设计 2.1 热释电传感器介绍 热释电红外…