C++单例模式与多例模式

C++ 单例模式的设计意图

单例模式(Singleton Pattern) 是一种创建型设计模式,其主要目的是确保一个类只有一个实例,并提供一个全局访问点。单例模式常用于需要全局唯一实例的场景,例如:

  1. 日志记录器:在整个应用程序中,只需要一个日志记录器实例来记录所有的日志信息。
  2. 配置管理器:应用程序的配置信息通常只需要一个实例来管理。
  3. 数据库连接池:在整个应用程序中,只需要一个数据库连接池实例来管理数据库连接。

单例模式的实现方式

单例模式的实现方式主要有两种:懒汉式(Lazy Initialization) 和 饿汉式(Eager Initialization)

懒汉型单例模式

懒汉式单例模式在第一次使用时才创建实例,因此它具有延迟加载的特性。如果单例对象的创建成本较高,懒汉式可以在需要时才进行创建,从而提高性能。

#include <iostream>
#include <mutex>class Singleton {
private:static Singleton* instance;static std::mutex mtx;// 构造函数私有化,防止外部创建实例Singleton() {std::cout << "Singleton instance created." << std::endl;}public:// 获取单例实例static Singleton* getInstance() {// 双重检查锁定,确保线程安全if (instance == nullptr) {std::lock_guard<std::mutex> lock(mtx);if (instance == nullptr) {instance = new Singleton();}}return instance;}// 删除拷贝构造函数和赋值运算符,防止拷贝Singleton(Singleton const&) = delete;Singleton& operator=(Singleton const&) = delete;// 销毁实例static void destroyInstance() {delete instance;instance = nullptr;}// 测试方法void showMessage() {std::cout << "Hello from Singleton!" << std::endl;}
};// 静态成员变量初始化
Singleton* Singleton::instance = nullptr;
std::mutex Singleton::mtx;int main() {Singleton* s1 = Singleton::getInstance();Singleton* s2 = Singleton::getInstance();s1->showMessage();s2->showMessage();if (s1 == s2) {std::cout << "s1 and s2 are the same instance." << std::endl;} else {std::cout << "s1 and s2 are different instances." << std::endl;}Singleton::destroyInstance();return 0;
}

饿汉型单例模式

饿汉式单例模式在程序启动时就创建实例,而不是在第一次使用时创建。由于实例在程序启动时就创建,因此它的实现相对简单,不需要考虑线程安全问题。

#include <iostream>class Singleton {
private:static Singleton* instance;// 构造函数私有化,防止外部创建实例Singleton() {std::cout << "Singleton instance created." << std::endl;}public:// 获取单例实例static Singleton* getInstance() {return instance;}// 删除拷贝构造函数和赋值运算符,防止拷贝Singleton(Singleton const&) = delete;Singleton& operator=(Singleton const&) = delete;// 销毁实例static void destroyInstance() {delete instance;instance = nullptr;}// 测试方法void showMessage() {std::cout << "Hello from Singleton!" << std::endl;}
};// 静态成员变量初始化
Singleton* Singleton::instance = new Singleton();int main() {Singleton* s1 = Singleton::getInstance();Singleton* s2 = Singleton::getInstance();s1->showMessage();s2->showMessage();if (s1 == s2) {std::cout << "s1 and s2 are the same instance." << std::endl;} else {std::cout << "s1 and s2 are different instances." << std::endl;}Singleton::destroyInstance();return 0;
}

多线程安全版单例模式

多线程安全的单例模式通常采用**双重检查锁定(Double-Checked Locking)**技术,确保在多线程环境下只有一个实例被创建。

#include <iostream>
#include <mutex>class Singleton {
private:static Singleton* instance;static std::mutex mtx;// 构造函数私有化,防止外部创建实例Singleton() {std::cout << "Singleton instance created." << std::endl;}public:// 获取单例实例static Singleton* getInstance() {// 双重检查锁定,确保线程安全if (instance == nullptr) {std::lock_guard<std::mutex> lock(mtx);if (instance == nullptr) {instance = new Singleton();}}return instance;}// 删除拷贝构造函数和赋值运算符,防止拷贝Singleton(Singleton const&) = delete;Singleton& operator=(Singleton const&) = delete;// 销毁实例static void destroyInstance() {delete instance;instance = nullptr;}// 测试方法void showMessage() {std::cout << "Hello from Singleton!" << std::endl;}
};// 静态成员变量初始化
Singleton* Singleton::instance = nullptr;
std::mutex Singleton::mtx;int main() {Singleton* s1 = Singleton::getInstance();Singleton* s2 = Singleton::getInstance();s1->showMessage();s2->showMessage();if (s1 == s2) {std::cout << "s1 and s2 are the same instance." << std::endl;} else {std::cout << "s1 and s2 are different instances." << std::endl;}Singleton::destroyInstance();return 0;
}

总结

  • 懒汉式单例模式:在第一次使用时创建实例,适用于实例创建成本较高的情况,但需要考虑线程安全问题。
  • 饿汉式单例模式:在程序启动时创建实例,实现简单,线程安全,但可能会导致资源浪费。
  • 多线程安全版单例模式:通过双重检查锁定技术确保在多线程环境下只有一个实例被创建。

C++ 多例模式示例代码

多例模式(Multiton Pattern) 是单例模式的一种扩展,它允许多个实例,每个实例都有一个唯一的标识符(例如名称)。通过这种方式,可以在需要多个唯一实例的情况下使用多例模式。

在下面的示例中,我们将创建一个多例模式,使用 std::map 来存储实例和它们的名称。我们将创建固定数量的实例,并在需要时通过名称来获取它们。

代码示例

#include <iostream>
#include <map>
#include <string>
#include <memory>class Multiton {
private:// 实例名称std::string name;// 构造函数私有化,防止外部创建实例Multiton(const std::string& name) : name(name) {std::cout << "Multiton instance created: " << name << std::endl;}// 静态成员变量,用于存储多例实例static std::map<std::string, std::shared_ptr<Multiton>> instances;public:// 获取多例实例static std::shared_ptr<Multiton> getInstance(const std::string& name) {auto it = instances.find(name);if (it == instances.end()) {// 如果实例不存在,创建并存储它std::shared_ptr<Multiton> instance = std::make_shared<Multiton>(name);instances[name] = instance;return instance;}return it->second;}// 删除拷贝构造函数和赋值运算符,防止拷贝Multiton(Multiton const&) = delete;Multiton& operator=(Multiton const&) = delete;// 测试方法void showMessage() {std::cout << "Hello from Multiton " << name << "!" << std::endl;}
};// 静态成员变量初始化
std::map<std::string, std::shared_ptr<Multiton>> Multiton::instances;int main() {// 创建固定数量的实例,每个实例有一个名称std::shared_ptr<Multiton> m1 = Multiton::getInstance("Instance1");std::shared_ptr<Multiton> m2 = Multiton::getInstance("Instance2");std::shared_ptr<Multiton> m3 = Multiton::getInstance("Instance3");// 获取已经创建的实例std::shared_ptr<Multiton> m4 = Multiton::getInstance("Instance1");std::shared_ptr<Multiton> m5 = Multiton::getInstance("Instance2");std::shared_ptr<Multiton> m6 = Multiton::getInstance("Instance3");// 测试方法调用m1->showMessage();m2->showMessage();m3->showMessage();m4->showMessage();m5->showMessage();m6->showMessage();// 检查实例是否相同if (m1 == m4 && m2 == m5 && m3 == m6) {std::cout << "The instances are the same." << std::endl;} else {std::cout << "The instances are different." << std::endl;}return 0;
}

代码说明

  1. 私有构造函数Multiton 类的构造函数是私有的,防止外部直接创建实例。
  2. 静态成员变量 instances:使用 std::map 存储实例名称和对应的实例指针。
  3. getInstance 方法:通过名称获取实例。如果实例不存在,则创建并存储它。
  4. showMessage 方法:用于测试实例是否正常工作。

输出结果

运行上述代码后,输出结果将显示每个实例的创建信息,并验证通过相同名称获取的实例是否相同。

Multiton instance created: Instance1
Multiton instance created: Instance2
Multiton instance created: Instance3
Hello from Multiton Instance1!
Hello from Multiton Instance2!
Hello from Multiton Instance3!
Hello from Multiton Instance1!
Hello from Multiton Instance2!
Hello from Multiton Instance3!
The instances are the same.

总结

多例模式通过 std::map 存储多个实例,每个实例都有一个唯一的标识符(例如名称)。通过这种方式,可以在需要多个唯一实例的情况下使用多例模式,并且可以方便地通过标识符获取实例。

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

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

相关文章

设计模式之装饰器模式(SSO单点登录功能扩展,增加拦截用户访问方法范围场景)

前言&#xff1a; 两个本想描述一样的意思的词&#xff0c;只因一字只差就让人觉得一个是好牛&#xff0c;一个好搞笑。往往我们去开发编程写代码时也经常将一些不恰当的用法用于业务需求实现中&#xff0c;但却不能意识到。一方面是由于编码不多缺少较大型项目的实践&#xff…

鸿蒙HarmonyOS 地图不显示解决方案

基于地图的开发准备已完成的情况下&#xff0c;地图还不显式的问题 首先要获取设备uuid 获取设备uuid 安装DevEco Studio的路径下 有集成好的hdc工具 E:\install_tools\DevEco Studio\sdk\default\openharmony\toolchains 这个路径下打开cmd运行 进入“设置 > 关于手机…

【C语言】值传递和地址传递

值传递 引用传递&#xff08;传地址&#xff0c;传引用&#xff09;的区别 传值&#xff0c;是把实参的值赋值给行参 &#xff0c;那么对行参的修改&#xff0c;不会影响实参的值。 传地址&#xff0c;是传值的一种特殊方式&#xff0c;只是他传递的是地址&#xff0c;不是普通…

C语言入门到精通(第六版)——第十六章

16、网络套接字编程 16.1、计算机网络基础 计算机网络技术是计算机技术和通信技术相结合的产物&#xff0c;代表计算机的一个重要发展方向。了解计算机的网络结构&#xff0c;有助于用户开发网络应用程序。 16.1.1、IP地址 为了使网络上的计算机能够彼此识别对方&#xff0c;…

Cyberchef配合Wireshark提取并解析HTTP/TLS流量数据包中的文件

本文将介绍一种手动的轻量级的方式&#xff0c;还原HTTP/TLS协议中传输的文件&#xff0c;为流量数据包中的文件分析提供帮助。 如果捕获的数据包中存在非文本类文件&#xff0c;例如png,jpg等图片文件&#xff0c;或者word&#xff0c;Excel等office文件异或是其他类型的二进…

记录使用documents4j来将word文件转化为pdf文件

本文记录使用documents4j来将word文件转化为pdf文件 文章目录 程序实例maven导入代码实现程序结果 本文小结 程序实例 maven导入 <!--word转pdf--><dependency><groupId>com.documents4j</groupId><artifactId>documents4j-local</artifactI…

SQL面试题——奔驰SQL面试题 车辆在不同驾驶模式下的时间

SQL面试题——奔驰SQL面试题 我们的表大致如下 CREATE TABLE signal_log( vin STRING COMMENTvehicle frame id, signal_name STRING COMMENTfunction name, signal_value STRING COMMENT signal value , ts BIGINT COMMENTevent timestamp, dt STRING COMMENTformat yyyy-mm…

使用 unicorn 和 capstone 库来模拟 ARM Thumb 指令的执行(一)

import binascii import unicorn import capstonedef printArm32Regs(mu):for i in range(66,78):print("R%d,value:%x"%(i-66,mu.reg_read(i)))def testhumb():CODE b\x1C\x00\x0A\x46\x1E\x00"""MOV R3, R0 的机器码&#xff1a;0x1C 0x00&#xf…

WordPress 6.7 “Rollins”发布

每个 WordPress 版本都会向一位在音乐界留下不可磨灭印记的艺术家致敬。WordPress 6.7 的代号为“Rollins”&#xff0c;旨在向传奇爵士萨克斯演奏家桑尼罗林斯致敬。罗林斯是爵士乐界最伟大的即兴演奏家和先驱之一&#xff0c;他以精湛的技术、创新精神和无畏的音乐表达方式影…

844.比较含退格的字符串

java用 O&#xff08;1&#xff09;空间这个方法&#xff0c;容易挺多bug的… O&#xff08;1&#xff09;空间 #&#xff1a;删除前一个字符 》 从后面开始判断&#xff08;这样可以用跳过的思想&#xff09;不能使用两次 i- - 来处理 # 的操作&#xff0c;会造成误删了前面…

WLAN消失或者已连接但是访问不了互联网

目录 1、WLAN已连接但是访问不了互联网 2、WLAN图标消失 今晚电脑突然连不上网了&#xff0c;重启试了好多种办法都没有用。 1、WLAN已连接但是访问不了互联网 这个的问题很多&#xff0c;建议直接网络重置&#xff0c;即将网络驱动全部删除&#xff0c;然后重新安装。 首先…

Linux源码阅读笔记-V4L2框架基础介绍

V4L2视频设备驱动基础 V4L2 是专门为 Linux 设备设计的整套视频框架&#xff08;其主要核心在 Linux 内核&#xff0c;相当于 Linux 操作系统上层的视频源捕获驱动框架&#xff09;。为上层访问系统底层的视频设备提供一个统一的标准接口。V4L2 驱动框架能够支持多种类型设备&…

C 语言 【模拟实现内存库函数】

1、memcpy memcpy函数是C/C语言中的一个用于内存复制的函数&#xff0c;声明在 string.h 中&#xff08;C是 cstring&#xff09;。其原型是&#xff1a; void * memcpy ( void * destination, const void * source, size_t num ); 其中&#xff0c;destination表示的是要拷贝…

【大数据学习 | flume】flume的概述与组件的介绍

1. flume概述 Flume是cloudera(CDH版本的hadoop) 开发的一个分布式、可靠、高可用的海量日志收集系统。它将各个服务器中的数据收集起来并送到指定的地方去&#xff0c;比如说送到HDFS、Hbase&#xff0c;简单来说flume就是收集日志的。 Flume两个版本区别&#xff1a; ​ 1&…

01:(手撸HAL+CubeMX)时钟篇

&#xff08;手撸HALCubeMX&#xff09;时钟篇 1、对SystemInit函数的分析2、使用HSI将总线时钟配置为最高频率3、使用HSE将总线时钟配置为最高频率4、使用Cube配置时钟树的参数5、对HAL_Init函数分析6、对系统定时器中断服务函数分析 有关时钟树和上电/复位的基础知识请参考“…

大数据新视界 -- 大数据大厂之 Impala 存储格式转换:从原理到实践,开启大数据性能优化星际之旅(下)(20/30)

&#x1f496;&#x1f496;&#x1f496;亲爱的朋友们&#xff0c;热烈欢迎你们来到 青云交的博客&#xff01;能与你们在此邂逅&#xff0c;我满心欢喜&#xff0c;深感无比荣幸。在这个瞬息万变的时代&#xff0c;我们每个人都在苦苦追寻一处能让心灵安然栖息的港湾。而 我的…

Spring Boot实现文件上传与OSS集成:从基础到应用

目录 前言1. 文件上传的基础实现1.1 前端文件上传请求1.2 后端文件接收与保存 2. 集成第三方OSS服务2.1 准备工作2.2 编写OSS集成代码2.3 修改Controller实现文件上传至OSS 3. 文件上传的扩展&#xff1a;多文件上传与权限控制结语 前言 随着互联网应用的快速发展&#xff0c;…

微服务各组件整合

nacos 第一步&#xff0c;引入依赖 <dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency> 第二步&#xff0c;增加配置 spring:application:name: …

机器学习总结

机器学习按照模型类型分为监督学习模型&#xff0c;无监督学习模型和概率模型三大类&#xff1a; 下图是机器学习笔记思维导图&#xff0c;&#xff1a; 一.什么是机器学习 从本质上讲&#xff0c;可以认为机器学习就是在数据中寻找一种合适的函数来描述输入与输出之间的关系。…

WEB攻防-通用漏洞SQL注入sqlmapOracleMongodbDB2等

SQL注入课程体系&#xff1a; 1、数据库注入-access mysql mssql oracle mongodb postgresql 2、数据类型注入-数字型 字符型 搜索型 加密型&#xff08;base64 json等&#xff09; 3、提交方式注入-get post cookie http头等 4、查询方式注入-查询 增加 删除 更新 堆叠等 …