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.rhkb.cn/news/381477.html

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

相关文章

新能源风机视觉数据集

需要的同学私信联系&#xff0c;推荐关注上面图片右下角平台自取下载。 全球风电装机的快速扩张推高了风电场运维巡检的需求&#xff0c;原本高度依赖人力的风电运维巡检工作正因智能化、数字化、无人化技术的应用出现变革。AI智慧风机检测可以促进风电领域运维检测新技术产、…

操作系统——文件管理

1&#xff09;什么是文件&#xff1f; 2&#xff09;单个文件的逻辑结构和物理结果之间是否存在制约关系&#xff1f; 本节内容较为抽象&#xff0c;本节要注意区分文件的逻辑结构和物理结构。 一、文件系统基础 1.文件的基本概念&#xff08;一切皆文件&#xff09; 文件&…

【漏洞复现】Netgear WN604 downloadFile.php 信息泄露漏洞(CVE-2024-6646)

0x01 产品简介 NETGEAR WN604是一款由NETGEAR&#xff08;网件&#xff09;公司生产的无线接入器&#xff08;或无线路由器&#xff09;提供Wi-Fi保护协议&#xff08;WPA2-PSK, WPA-PSK&#xff09;&#xff0c;以及有线等效加密&#xff08;WEP&#xff09;64位、128位和152…

AVL树超详解上

前言 学习过了二叉树以及二叉搜索树后&#xff08;不了解二叉搜索树的朋友可以先看看这篇博客&#xff0c;二叉搜索树详解-CSDN博客&#xff09;&#xff0c;我们在一般情况下对于二叉搜索树的插入与查询时间复杂度都是O(lgN)&#xff0c;是十分快的&#xff0c;但是在一些特殊…

视频监控平台LntonCVS视频融合共享平台智慧安防视频监控汇聚应用方案

LntonCVS是一款功能强大且灵活部署的安防视频监控平台。它支持多种主流标准协议&#xff0c;包括GB28181、RTSP/Onvif、RTMP等&#xff0c;同时能够兼容海康Ehome、海大宇等厂家的私有协议和SDK接入。该平台不仅提供传统的安防监控功能&#xff0c;还支持接入AI智能分析&#x…

医疗器械产品的 EMC(电磁兼容性)中A、B、C、D 类的区别是什么

在医疗器械产品的 EMC&#xff08;电磁兼容性&#xff09;中&#xff0c;按照 GB 17625.1 标准的分类&#xff0c;A、B、C、D 类的区别主要在于设备的谐波电流发射限值不同。 A 类设备&#xff1a;平衡的三相设备、不归属 B、C 或 D 类的设备、家用电器&#xff08;不包括列入 …

TiDB实践—索引加速+分布式执行框架创建索引提升70+倍

作者&#xff1a; 数据源的TiDB学习之路 原文来源&#xff1a; https://tidb.net/blog/92d348c2 背景介绍 TiDB 采用在线异步变更的方式执行 DDL 语句&#xff0c;从而实现 DDL 语句的执行不会阻塞其他会话中的 DML 语句。按照是否需要操作 DDL 目标对象所包括的数据来划分…

直播带货还是新电商吗?

现在已经没有新电商和老电商区分&#xff0c;抖音现直播电商现在也算是传统电商了。直播电商这几年听起来非常的火热&#xff0c;但是它有天花板&#xff0c;最多也就3万亿的市场规模&#xff0c;为什么呢&#xff1f;因为它是基于 IP 模型的&#xff0c;有非常强的头部效应。 …

一分钟图情论文:《叙事信息的语义表示与组织结构研究》

叙事作为人类知识与信息交流的重要方式&#xff0c;其语义建模、形式化表示与组织在数智时代显得尤为重要。近日&#xff0c;由曲阜师范大学和武汉大学的侯西龙、王晓光教授合著论文《叙事信息的语义表示与组织结构研究》从语义表示和组织结构视角出发审视了叙事信息的复杂性和…

电子画册制作利器大揭秘,提升销量全靠它

​随着科技的不断发展&#xff0c;电子画册逐渐成为企业营销的新宠。它以生动活泼、互动性强的特点&#xff0c;吸引了众多消费者的目光。而一款优秀的电子画册制作利器&#xff0c;更是为企业提升了销量&#xff0c;实现了营销目标。本文将为大家揭秘电子画册制作的利器&#…

《基于 Kafka + Quartz 实现时限质控方案》

&#x1f4e2; 大家好&#xff0c;我是 【战神刘玉栋】&#xff0c;有10多年的研发经验&#xff0c;致力于前后端技术栈的知识沉淀和传播。 &#x1f497; &#x1f33b; CSDN入驻不久&#xff0c;希望大家多多支持&#xff0c;后续会继续提升文章质量&#xff0c;绝不滥竽充数…

密码学基础-Hash、MAC、HMAC 的区别与联系

密码学基础-Hash、MAC、HMAC 的区别与联系 Hash Hash 是一种从一段数据中创建小的数字“指纹”的方法。就像一个人的指纹代表一个人的信息一样&#xff0c;Hash 对输入的数据进行整理&#xff0c;生成一个代表该输入数据的“指纹” 数据。通常该指纹数据也可称之为摘要、散列…

linux配置podman阿里云容器镜像加速器

1.下载podman yum install -y podman systemctl status podman systemctl start podman 2.获取阿里云个人容器镜像加速器地址 访问阿里云官网&#xff1a;首先&#xff0c;您需要访问阿里云&#xff08;Alibaba Cloud&#xff09;的官方网站。阿里云官网的URL是&#xff1a;…

TinyVue:与 Vue 交往八年的组件库

本文由体验技术团队莫春辉老师原创~ 去年因故停办的 VueConf&#xff0c;今年如约在深圳举行。作为东道主 & 上届 VueConf 讲师的我&#xff0c;没有理由不来凑个热闹。大会结束后&#xff0c;我见裕波在朋友圈转发 Jinjiang 的文章《我和 Vue.js 的十年》&#xff0c;我就…

如何发一篇顶会论文? 涉及3D高斯,slam,自动驾驶,三维点云等等

SLAM&3DGS 1&#xff09;SLAM/3DGS/三维点云/医疗图像/扩散模型/结构光/Transformer/CNN/Mamba/位姿估计 顶会论文指导 2&#xff09;基于环境信息的定位&#xff0c;重建与场景理解 3&#xff09;轻量级高保真Gaussian Splatting 4&#xff09;基于大模型与GS的 6D pose e…

【AI大模型】生成式AI的未来——CHAT还是AGENT?

【AI大模型】CHAt还是AGENt&#xff1f; 最近&#xff0c;许多人工智能公司或者部门都在针对Agent——人工智能体有所动作。 例如&#xff1a; 文心一言智能体 Gnomic智能体 英伟达视觉AI代理 那么人工智能概念中的智能体Agent到底是什么呢&#xff1f;它又为何会突然在人工智…

「网络通信」HTTP 协议

HTTP &#x1f349;简介&#x1f349;抓包工具&#x1f349;报文结构&#x1f34c;请求&#x1f34c;响应&#x1f34c;URL&#x1f95d;URL encode &#x1f34c;方法&#x1f34c;报文字段&#x1f95d;Host&#x1f95d;Content-Length & Content-Type&#x1f95d;User…

基于Nginx搭建RTMP流媒体服务器视频无法保存

文章目录 基于Nginx搭建RTMP流媒体服务器安装Nginx-RTMPNginx 配置文件 视频无法保存 基于Nginx搭建RTMP流媒体服务器 安装Nginx-RTMP 要实现RTMP流媒体服务器需要安装Nginx-RTMP模块 已有Nginx安装Nginx-RTMP模块 sudo apt update sudo apt install libnginx-mod-rtmp可能会…

pnpm build打包时占内溢出

这两天在打包H5网页的时候失败&#xff0c;总是提示下方错误 FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory 严重错误&#xff1a;堆限制附近标记压缩无效分配失败 - JavaScript 堆内存不足 尝试了多种方法&…

XXE:XML外部实体引入

XXE漏洞 如果服务器没有对客户端的xml数据进行限制&#xff0c;且版本较低的情况下&#xff0c;就可能会产生xxe漏洞 漏洞利用流程 1.客户端发送xml文件&#xff0c;其中dtd存在恶意的外部实体引用 2.服务器进行解析 3.服务器返回实体引用内容 危害&#xff1a;任意文件读…