C++_单例模式

目录

1、饿汉方式实现单例

2、懒汉方式实现单例

3、单例模式的总结 

结语


前言:

        在C++中有许多设计模式,单例模式就是其中的一种,该模式主要针对类而设计,确保在一个进程下该类只能实例化出一个对象,因此名为单例。而单例模式又分为饿汉方式和懒汉方式,饿汉方式指的是只要发出了对该类的需求,就会实例化对象。懒汉方式指的是即使发出了对该类的需求,但是不会立刻实例化对象,等到真正用到该对象时才会实例化对象。

        示意图如下:

1、饿汉方式实现单例

         饿汉方式表明只要提出需要,则立即用该类实例化对象,并且当前进程只能有一个该类型的对象。这个逻辑在代码中的体现是:只要我们提出需要某个类的实例化请求,则系统就会立即在物理内存中就会为该对象开辟空间,即使我们不对该对象做任何的使用,该对象也会静静的放在内存中。当我们真正要访问该对象时,只能通过唯一的途径访问。

        代码实现饿汉方式:

#include <iostream>
#include <unistd.h>using namespace std;class Singleton
{Singleton()//该类不能在外被构造{cout<<"程序运行时就打印该信息"<<endl;}~Singleton(){}//该类不能在外被析构Singleton(const Singleton& )=delete;//该类不能在外被拷贝Singleton& operator=(const Singleton& )=delete;//该类不能在外被赋值static Singleton data;//该进程下唯一Singleton对象,即单例
public:static Singleton *GetInstance()//外部只能通过调用该函数拿到data{return &data;}
};Singleton Singleton::data;//data的初始化int main()
{return 0;
}

        运行结果:

        从结果可以发现,代码中仅仅只是定义了一个类,还未手动对该类进行实例化,程序开始执行时系统就自动实例化了一个Singleton的data对象,因为Singleton类的构造函数被执行,说明构造了一个对象。

        对上述代码的逻辑可以理解为:定义Singleton类就是提出需求,而程序一启动就执行构造函数说明提出需求后就立即得到了一个对象


        并且在该进程下只存在唯一的Singleton类型对象,并且访问该唯一对象的途径只能是调用静态成员函数GetInstance,并且当调用GetInstance静态函数说明“真正用到了该对象”,测试代码如下:

#include <iostream>
#include <unistd.h>using namespace std;class Singleton
{Singleton()//该类不能在外被构造{cout<<"程序运行时就打印该信息"<<endl;}~Singleton(){}//该类不能在外被析构Singleton(const Singleton& )=delete;//该类不能在外被拷贝Singleton& operator=(const Singleton& )=delete;//该类不能在外被赋值static Singleton data;//该进程下唯一Singleton对象,即单例
public:static Singleton *GetInstance()//外部只能通过调用该函数拿到data{return &data;}
};Singleton Singleton::data;//data的初始化int main()
{//以下两种实例化方式都无法实例化出对象// Singleton s;// Singleton s1(s);cout<<Singleton::GetInstance()<<endl;return 0;
}

        运行结果:

2、懒汉方式实现单例

        懒汉方式指的是当提出需求后,系统不会立即实例化出对象,而是先实例化一个指针,当真正需要用到该对象时,系统才会主动的去申请一个对象,并让该指针指向这个对象。

        懒汉方式的代码如下:

#include <iostream>
#include <unistd.h>using namespace std;class Singleton // 懒汉
{Singleton() // 该类不能在外被构造{cout << "程序运行时就打印该信息" << endl;}~Singleton() {}                                   // 该类不能在外被析构Singleton(const Singleton &) = delete;            // 该类不能在外被拷贝Singleton &operator=(const Singleton &) = delete; // 该类不能在外被赋值static Singleton *data;       // 使用Singleton*作为访问唯一对象的入口static pthread_mutex_t lock_; // 保证线程安全
public:static Singleton *GetInstance() // 外部只能通过调用该函数拿到data指针{if (data == nullptr){pthread_mutex_lock(&lock_);if (data == nullptr)data = new Singleton();pthread_mutex_unlock(&lock_);}return data;}
};Singleton* Singleton::data = nullptr; // data的初始化
pthread_mutex_t Singleton::lock_ = PTHREAD_MUTEX_INITIALIZER;//锁的初始化int main()
{return 0;
}

        运行结果:

        可以发现,当程序一启动时,并没有直接构造一个Singleton类型的对象,因为没有调用Singleton的构造函数,只是简单的将data指针初始化为nullptr,只有当调用静态函数GetInstance时,系统才会实例化出对象,因为调用GetInstance表示要用到该对象,这时候就可以实例化对象了。


        调用函数GetInstance的代码如下:

#include <iostream>
#include <unistd.h>using namespace std;class Singleton // 懒汉
{Singleton() // 该类不能在外被构造{cout << "程序运行时就打印该信息" << endl;}~Singleton() {}                                   // 该类不能在外被析构Singleton(const Singleton &) = delete;            // 该类不能在外被拷贝Singleton &operator=(const Singleton &) = delete; // 该类不能在外被赋值static Singleton *data;       // 使用Singleton*作为访问唯一对象的入口static pthread_mutex_t lock_; // 保证线程安全
public:static Singleton *GetInstance() // 外部只能通过调用该函数拿到data指针{if (data == nullptr){pthread_mutex_lock(&lock_);if (data == nullptr)data = new Singleton();pthread_mutex_unlock(&lock_);}return data;}
};Singleton* Singleton::data = nullptr; // data的初始化
pthread_mutex_t Singleton::lock_ = PTHREAD_MUTEX_INITIALIZER;//锁的初始化int main()
{//只有调用GetInstance时,才会开辟空间cout << Singleton::GetInstance() << endl;return 0;
}

        运行结果:

        从结果可以看到,只要真正要用到该对象,系统才会实例化该对象,没有用到该对象前,系统只有一个指针做“准备就绪”的工作。 

3、单例模式的总结 

        不管是饿汉方式还是懒汉方式,基本实现都是依靠static修饰的成员变量,并且该静态变量要放在类内,因为单例模式下构造函数是在私有域中的, 静态变量只有在类内才可以调用该类的构造函数进行初始化,这也从侧面表示出静态成员变量的类型必须和当前类的类型是一样的。拿到该类的实例化对象的途径只有通过调用该类的静态成员函数去访问。

        一般懒汉方式用的最多,因为懒汉在局部上加快了速度,因为他改变的是花费时间的结构,比如要加载某个任务,若把整个任务都加载下来则需要很多时间,但是我们可以先加载任务的一小部分先用上,而无需等待整个任务都加载下来,等到真正使用该任务的时候在进行下载,可以将空间利用率最大化。

结语

        以上就是关于单例模式的讲解,单例模式下用的最多的是懒汉方式,因为他可以将内存的空间利用率最大化,无论是饿汉方式还是懒汉方式,本质上是利用了static静态变量在进程的唯一性。

        最后如果本文有遗漏或者有误的地方欢迎大家在评论区补充,谢谢大家!! 

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

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

相关文章

temu数据分析怎么做,temu选品数据分析怎么做

在竞争激烈的电商市场中&#xff0c;数据分析已成为商家提升销售业绩、优化经营策略的重要工具。特别是对于Temu平台的卖家而言&#xff0c;掌握数据分析技巧&#xff0c;特别是选品数据分析&#xff0c;更是至关重要。本文将为您详细解析如何在Temu平台上进行数据分析&#xf…

Docker 安全及日志管理(包含SSL证书)

目录 一、Docker 存在的安全问题 二、Docker 架构缺陷与安全机制 三、Docker 安全基线标准 四、容器相关的常用安全配置方法 五、限制流量流向 六、镜像安全 七、DockerClient 端与 DockerDaemon 的通信安全 https的单向认证流程 https的双向认证流程 八、DockerClie…

Ubuntu 22.04.4 LTS (linux) GoAccess 分析 Nginx 日志

1 安装goaccess sudo apt-get update sudo apt-get install goaccess 2 控制台运行 goaccess -a -d -f /usr/local/openresty/nginx/logs/access.log -p /etc/goaccess/goaccess.conf #sudo vim /etc/goaccess/goaccess.conf time-format %H:%M:%S date-format %d/%b…

iOS ------ Block的相关问题

Block的定义 Block可以截获局部变量的匿名函数&#xff0c; 是将函数及其执行上下文封装起来的对象。 Block的实现 通过Clang将以下的OC代码转化为C代码 // Clang xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc main.m//main.m #import <Foundation/Foundation.…

3.2、数据结构-数组、矩阵和广义表

数组结构 数组是定长线性表在维度上的扩展,即线性表中的元素又是一个线性表。N维数组是一种“同构”的数据结构,其每个数据元素类型相同、结构一致。 一个m行n列的数组表示如下: 其可以表示为行向量形式&#xff08;一行一行的数据&#xff09;或者列向量形式&#xff08;一…

Nginx 怎样处理请求的故障转移?

&#x1f345;关注博主&#x1f397;️ 带你畅游技术世界&#xff0c;不错过每一次成长机会&#xff01; 文章目录 Nginx 怎样处理请求的故障转移&#xff1f;一、理解故障转移的重要性二、Nginx 中的故障检测机制三、Nginx 中的请求分配策略四、Nginx 中的故障转移实现方式五、…

Shell脚本编程(一)

目录 一、Shell命令行的书写规则 二、编写/修改权限及执行shell程序的步骤 1、编写简单Shell程序 2、建立可执行程序 3、执行Shell程序 4、实例 三、Shell程序中使用参数 1、位置参数 2、内部参数 3、实例一 4、实例二 一、Shell命令行的书写规则 在执行Shell命令时…

搭建本地私有知识问答系统:MaxKB + Ollama + Llama3 (wsl网络代理配置、MaxKB-API访问配置)

目录 搭建本地私有知识问答系统:MaxKB、Ollama 和 Llama3 实现指南引言MaxKB+Ollama+Llama 3 Start buildingMaxKB 简介:1.1、docker部署 MaxKB(方法一)1.1.1、启用wls或是开启Hyper使用 WSL 2 的优势1.1.2、安装docker1.1.3、docker部署 MaxKB (Max Knowledge Base)MaxKB …

便携式气象仪:科技赋能,让气象观测更智能

随着科技的快速发展&#xff0c;越来越多的领域受益于技术的进步。其中&#xff0c;气象观测领域也不例外。传统的气象观测设备虽然精确可靠&#xff0c;但往往体积庞大、携带不便&#xff0c;且需要专业人员进行操作和维护。而便携式气象仪的出现&#xff0c;则打破了这一局限…

在WPF中使用WebView2详解

Microsoft Edge WebView2 Microsoft Edge WebView2 控件允许在本机应用中嵌入 web 技术(HTML、CSS 以及 JavaScript)。 WebView2 控件使用 Microsoft Edge 作为绘制引擎&#xff0c;以在本机应用中显示 web 内容。 使用 WebView2 可以在本机应用的不同部分嵌入 Web 代码&…

Golang | Leetcode Golang题解之第284题窥视迭代器

题目&#xff1a; 题解&#xff1a; type PeekingIterator struct {iter *Iterator_hasNext bool_next int }func Constructor(iter *Iterator) *PeekingIterator {return &PeekingIterator{iter, iter.hasNext(), iter.next()} }func (it *PeekingIterator) hasNe…

学习记录day19——数据结构 查找算法

概念 在给定数据元素的某个值&#xff0c;在查找表中确定一个其关键字等于给定值的数据元素的操作&#xff0c;叫做查找 查找的分类 顺序查找:将待查找数据&#xff0c;进行全部遍历一遍&#xff0c;直到找到要查找的元素 折半查找:每次都去除一半的查找范围的查找方式&#x…

vue3响应式用法(高阶性能优化)

文章目录 前言&#xff1a;一、 shallowRef()二、 triggerRef()三、 customRef()四、 shallowReactive()五、 toRaw()六、 markRaw()七、 shallowReadonly()小结&#xff1a; 前言&#xff1a; 翻别人代码时&#xff0c;总结发现极大部分使用vue3的人只会用ref和reactive处理响…

mysql-bin 恢复数据库

能看到这里的同学估计肯定摊上大事了吧&#xff01;不要慌&#xff0c;一定要冷静&#xff0c;记录一下作者的大事件吧&#xff0c;黑客通过SQL注入的方式执行了一段SQL &#xff1a; DROP DATABASE ****** 后果就是导致整个数据库被删了&#xff0c;当时心是拔凉拔凉的&#x…

在jmeter中使用javascript脚本

工作上遇到一个压力测试的需求&#xff0c;需要测试几个考试相关的接口。其中有一个获取试题详情的接口&#xff0c;和一个提交答题信息的接口。后一个接口以上一接口的返回内容为参数&#xff0c;添加上用户的答案即可。jmeter提供了非常多的方式可以实现该需求&#xff0c;这…

【深度学习】大模型GLM-4-9B Chat ,微调与部署(3) TensorRT-LLM、TensorRT量化加速、Triton部署

文章目录 获取TensorRT-LLM代码&#xff1a;构建docker镜像并安装TensorRT-LLM&#xff1a;运行docker镜像&#xff1a;安装依赖魔改下部分package代码&#xff1a;量化&#xff1a;构建图&#xff1a;全局参数插件配置常用配置参数 测试推理是否可以代码推理CLI推理 性能测试小…

钡铼网关实时数据互联,加速IEC104与MQTT云平台对接

随着工业4.0时代的到来&#xff0c;电力系统中的数据采集、监控与远程控制需求日益增长。IEC 104&#xff08;IEC 60870-5-104&#xff09;作为国际电工委员会&#xff08;IEC&#xff09;制定的电力自动化通信协议&#xff0c;广泛应用于电力系统的状态监测、数据采集和设备控…

Vue实现简单小案例

一、创建文件夹 二、引用vue.js <script src"../js/vue.js"></script> 三、准备一个容器 <div id"app"><h1>Hello,{{name}}</h1> </div> 四、创建实例 <script>new Vue({el:"#app", //el用于指…

【STM32 FreeRTOS】FreeRTOS的移植

其实这篇文章不侧重移植&#xff0c;因为我们会使用CubeMX配置&#xff0c;那样会自动移植FreeRTOS。 关于FreeRTOS&#xff0c;可以参考官网&#xff1a;FreeRTOS - Quick start guide 当我们在CubeMX中配置了CMSIS_V2后尝试编译的时候会有一个弹窗。 第一个问题就是强烈建议…

【深度学习】yolov8-det目标检测训练,拼接图的分割复原

项目背景 https://blog.csdn.net/x1131230123/article/details/140606459 似乎这个任务是简单的&#xff0c;利用目标检测是否可以完成得好呢? 生成数据集 利用这个代码产生数据集&#xff1a; 为了将标签转换为YOLOv5格式&#xff0c;需要将左上角和右下角的坐标转换为Y…