C++—单例设计模式

单例设计模式

C++中的单例设计模式是一种常用的软件设计模式,其核心目的是确保一个类仅有一个实例,并提供一个全局访问点来获取这个实例。以下是对C++单例设计模式的详细解释:

一、单例设计模式的定义

单例模式(Singleton Pattern)是一种创建型设计模式,它确保一个类只有一个实例,并提供一个全局访问点来获取这个实例。

二、单例设计模式的实现方式

在C++中,单例模式的实现方式多种多样,但基本思想都是将构造函数私有化,并通过一个静态方法提供类的唯一实例。以下是几种常见的实现方式:

  1. 懒汉式(线程不安全)
    • 延迟加载实例,即在需要时才创建实例。
    • 但在多线程环境下存在线程安全问题。
  2. 懒汉式(线程安全)
    • 通过加锁(如使用std::mutex)来保证在多线程环境下的线程安全。
    • 但每次访问实例时都需要加锁,可能会影响性能。
  3. 饿汉式
    • 在程序启动时立即创建实例,因此本身是线程安全的。
    • 但无论是否使用实例,都会立即创建,可能会浪费资源。
  4. 双重检查锁定(Double-Check Locking)
    • 一种优化懒汉式线程安全实现的方法。
    • 通过两次检查实例是否存在来减少加锁的次数,从而提高性能。
  5. 静态局部变量(C++11推荐)
    • 利用C++11中静态局部变量的线程安全特性来实现单例。
    • 这种方法既实现了延迟加载,又保证了线程安全。
  6. 使用智能指针
    • 将实例封装在智能指针中,如std::unique_ptrstd::shared_ptr,以自动管理内存。
  7. 使用std::call_once
    • C++11引入的std::call_once函数可以保证某个函数在程序执行期间只被调用一次。
    • 可以利用这个特性来实现线程安全的单例初始化。

三、单例设计模式的优缺点

优点

  1. 控制资源访问:确保对共享资源的独占访问。
  2. 简化全局访问:提供一个全局访问点,方便使用。
  3. 实现数据共享:可以在多个对象之间共享数据。

缺点

  1. 单例对象生命周期管理困难:单例对象通常在整个应用程序的生命周期内都存在,这可能导致资源无法及时释放。
  2. 扩展性差:如果需要创建多个实例,则需要对代码进行较大修改。
  3. 隐藏类的依赖关系:使用单例模式的类通常与其他类紧密耦合,这可能导致代码难以理解和维护。

四、单例设计模式的应用场景

单例设计模式适用于以下场景:

  1. 全局配置管理:如读取配置文件并管理配置信息。
  2. 数据库连接池:管理数据库连接,确保全局只有一个连接池。
  3. 日志记录器:确保全局只有一个日志记录器实例,用于记录应用程序的日志信息。
  4. 状态管理:在需要全局状态管理的场景中,如游戏开发中的游戏状态管理等。

总之,C++中的单例设计模式是一种非常有用的设计模式,但在使用时需要注意其优缺点和适用场景,以避免过度使用或误用导致的问题。

五、案例测试

1.懒汉式(线程安全)

#include <iostream>  
#include <mutex>  class Singleton {  
private:  static Singleton* instance;  static std::mutex mtx;  Singleton() {} // 私有构造函数,防止外部直接创建实例  // 禁止拷贝构造函数和赋值运算符  Singleton(const Singleton&) = delete;  Singleton& operator=(const Singleton&) = delete;  public:  static Singleton* getInstance() {  std::lock_guard<std::mutex> lock(mtx); // 使用锁保护  if (!instance) {  instance = new Singleton();  }  return instance;  }  void doSomething() {  std::cout << "Doing something..." << std::endl;  }  // 静态成员需要在类外初始化  static Singleton* instance_init() {  return nullptr;  }  static std::mutex mtx_init() {  return std::mutex();  }  
};  // 初始化静态成员  
Singleton* Singleton::instance = Singleton::instance_init();  
std::mutex Singleton::mtx = Singleton::mtx_init();  int main() {  Singleton* s1 = Singleton::getInstance();  Singleton* s2 = Singleton::getInstance();  if (s1 == s2) {  std::cout << "s1 and s2 are the same instance." << std::endl;  }  s1->doSomething();  s2->doSomething();  return 0;  
}

注意:虽然上面的代码使用了std::mutex来保证线程安全,但在实际使用中,如果单例的创建和销毁不是性能瓶颈,并且你确信单例的创建是线程安全的(例如,在程序启动时由主线程创建),那么可能不需要额外的线程安全措施。

2.静态局部变量(C++11推荐)

#include <iostream>  class Singleton {  
private:  Singleton() {} // 私有构造函数,防止外部直接创建实例  // 禁止拷贝构造函数和赋值运算符  Singleton(const Singleton&) = delete;  Singleton& operator=(const Singleton&) = delete;  static Singleton& getInstanceHelper() {  static Singleton instance; // 局部静态变量,线程安全  return instance;  }  public:  static Singleton& getInstance() {  return getInstanceHelper();  }  void doSomething() {  std::cout << "Doing something..." << std::endl;  }  
};  int main() {  Singleton& s1 = Singleton::getInstance();  Singleton& s2 = Singleton::getInstance();  // s1 和 s2 实际上是同一个实例的引用  std::cout << "&s1: " << &s1 << std::endl;  std::cout << "&s2: " << &s2 << std::endl;  s1.doSomething();  s2.doSomething();  return 0;  
}

在这个例子中,我使用了C++11的局部静态变量特性来确保单例的线程安全性和懒加载。这种方法既简单又高效,是推荐的实现方式之一。注意,由于我们返回的是引用而不是指针,因此不需要担心内存管理问题。

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

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

相关文章

精密制造的革新:光谱共焦传感器与工业视觉相机的融合

在现代精密制造领域&#xff0c;对微小尺寸、高精度产品的检测需求日益迫切。光谱共焦传感器凭借其非接触、高精度测量特性脱颖而出&#xff0c;而工业视觉相机则以其高分辨率、实时成像能力著称。两者的融合&#xff0c;不仅解决了传统检测方式在微米级别测量上的局限&#xf…

【C++】入门基础知识-1

&#x1f36c;个人主页&#xff1a;Yanni.— &#x1f308;数据结构&#xff1a;Data Structure.​​​​​​ &#x1f382;C语言笔记&#xff1a;C Language Notes &#x1f3c0;OJ题分享&#xff1a; Topic Sharing 目录 前言&#xff1a; C关键字 命名空间 命名空间介…

使用 Llama-index 实现的 Agentic RAG-Router Query Engine

前言 你是否也厌倦了我在博文中经常提到的老式 RAG(Retrieval Augmented Generation | 检索增强生成) 系统&#xff1f;反正我是对此感到厌倦了。但我们可以做一些有趣的事情&#xff0c;让它更上一层楼。接下来就跟我一起将 agents 概念引入传统的 RAG 工作流&#xff0c;重新…

凌晨1点开播!Meta Connect 2024开发者大会,聚焦Llama新场景和AR眼镜

作者&#xff1a;十九 编辑&#xff1a;李宝珠 北京时间 9 月 26 日凌晨 1 点&#xff0c;Meta Connect 2024 开发者大会即将举行&#xff0c;马克扎克伯格将聚焦 AI 和元宇宙&#xff0c;向大家分享 Llama 模型的更多潜在应用&#xff0c;并介绍 Meta 最新产品 AR 眼镜和 Meta…

OceanBase云数据库战略实施两年,受零售、支付、制造行业青睐

2022年OceanBase推出云数据库产品OB Cloud,正式启动云数据库战略。两年来OB Cloud发展情况如何&#xff0c;9月26日&#xff0c;OceanBase公有云事业部总经理尹博学向记者作了介绍。 尹博学表示&#xff0c;OB Cloud推出两年以来&#xff0c;已服务超过700家客户&#xff0c;客…

智算中心动环监控:构建高效、安全的数字基础设施@卓振思众

在当今快速发展的数字经济时代&#xff0c;智算中心作为人工智能和大数据技术的核心支撑设施&#xff0c;正日益成为各行业实现智能化转型的重要基石。为了确保这些高性能计算环境的安全与稳定&#xff0c;卓振思众动环监控应运而生&#xff0c;成为智算中心管理的重要组成部分…

理解Java引用数据类型(数组、String)传参机制的一个例子

目录 理解Java引用数据类型&#xff08;数组、String&#xff09;传参机制的一个例子理解样例代码输出 参考资料 理解Java引用数据类型&#xff08;数组、String&#xff09;传参机制的一个例子 理解 引用数据类型传递的是地址。用引用类型A给引用类型B赋值&#xff0c;相当于…

Linux(含麒麟操作系统)如何实现多显示器屏幕采集录制

技术背景 在操作系统领域&#xff0c;很多核心技术掌握在国外企业手中。如果过度依赖国外技术&#xff0c;在国际形势变化、贸易摩擦等情况下&#xff0c;可能面临技术封锁和断供风险。开发国产操作系统可以降低这种风险&#xff0c;确保国家关键信息基础设施的稳定运行。在一…

【C++位图】构建灵活的空间效率工具

目录 位图位图的基本概念如何用位图表示数据位图的基本操作setresettest 封装位图的设计 总结 在计算机科学中&#xff0c;位图&#xff08;Bitmap&#xff09;是一种高效的空间管理数据结构&#xff0c;广泛应用于各种场景&#xff0c;如集合操作、图像处理和资源管理。与传统…

一文读懂 Pencils Protocol 近期不可错过的市场活动

Pencils Protocol 是 Scroll 上综合性的 DeFi 协议&#xff0c;自 9 月 18 日开始其陆续在 Tokensoft、Bounce、Coresky 等平台开启 DAPP 通证的销售&#xff0c;并分别在短期内完成售罄。吸引了来自韩国、CIS、土耳其等 70 多个国家的 5 万多名认证用户&#xff0c;反响热烈&a…

Jmeter关联,断言,参数化

一、关联 常用的关联有三种 1.边界提取器 2.JSON提取器 3.正则表达式提取器 接下来就详细讲述一下这三种的用法 这里提供两个接口方便练习 登录接口 接口名称&#xff1a;登录 接口提交方式&#xff1a;POST 接口的url地址&#xff1a;https://admin-api.macrozheng.com/a…

C#常用数据结构栈的介绍

定义 在C#中&#xff0c;Stack<T> 是一个后进先出&#xff08;LIFO&#xff0c;Last-In-First-Out&#xff09;集合类&#xff0c;位于System.Collections.Generic 命名空间中。Stack<T> 允许你将元素压入栈顶&#xff0c;并从栈顶弹出元素。 不难看出&#xff0c;…

Vue引入js脚本问题记录(附解决办法)

目录 一、需求 二、import引入问题记录 三、解决方式 一、需求 我想在我的Vue项目中引入jquery.js和bootstrap.js这种脚本文件&#xff0c;但发现不能单纯的import引入&#xff0c;问题如下。 二、import引入问题记录 我直接这么引入&#xff0c;发现控制台报错TypeError: …

华为HarmonyOS地图服务 11 - 如何在地图上增加点注释?

场景介绍 本章节将向您介绍如何在地图的指定位置添加点注释以标识位置、商家、建筑等&#xff0c;并可以通过信息窗口展示详细信息。 点注释支持功能&#xff1a; 支持设置图标、文字、碰撞规则等。支持添加点击事件。 PointAnnotation有默认风格&#xff0c;同时也支持自定…

《强化学习的数学原理》(2024春)_西湖大学赵世钰 Ch9 策略梯度方法 Box 8.1 马尔可夫决策过程的平稳分布

Box 8.1&#xff1a; 马尔可夫决策过程的平稳分布 整理自 链接 分析平稳分布的关键工具是 P π ∈ R n n P_\pi \in {\mathbb R}^{n\times n} Pπ​∈Rnn&#xff0c;它是给定策略 π π π 下的概率转移矩阵。 如果状态被索引为 s 1 , ⋯ , s n s_1,\cdots, s_n s1​,⋯…

idea2021git从dev分支合并到主分支master

1、新建分支 新建一个名称为dev的分支&#xff0c;切换到该分支下面&#xff0c;输入新内容 提交代码到dev分支的仓库 2、切换分支 切换到主分支&#xff0c;因为刚刚提交的分支在dev环境&#xff0c;所以master是没有 3、合并分支 点击push&#xff0c;将dev里面的代码合并到…

图片尺寸不合适?这3款免费好用的AI绘图神器帮你免费无缝拓展!一键扩展画面之外的内容,真的泰裤啦!

大家好&#xff0c;我是灵魂画师向阳 在处理图片素材时&#xff0c;大家有没有遇到过尺寸不合适但又不能裁切的情况&#xff1f;是不是也想过图像要是能自己“长”出一块就好了&#xff1f;这种要求在以前或许很难实现&#xff0c;但生产式 AI 技术出现后它就不再是问题了&…

基于GIKT深度知识追踪模型的习题推荐系统源代码+数据库+使用说明,后端采用flask,前端采用vue

基于GIKT深度知识追踪模型的习题推荐系统 目录结构 Flask-BackEnd flask后端 app 后端主体文件 alg 深度学习模块 data 数据集data_process.py 数据预处理gikt.py GIKT模型pebg.py PEBG模型params.py 一些参数train.py 仅模型训练train_test.py 模型训练和测试-五折交叉验证t…

WebGIS开发四大开源框架对比

本篇文章主要介绍GIS开发四大地图框架的差异和特点。 Cesium: Cesium是目前主流的一款三维地图框架&#xff0c;支持桌面端、web端、移动端等多平台。Mapbox&#xff1a;高清经纬度矢量瓦片&#xff0c;个性化前端表达&#xff0c;前端矢量绘制&#xff0c;支持海量地名地址。…

数据库实验2—1

10-1 查询重量在[40,65]之间的产品信息 本题目要求编写SQL语句&#xff0c; 检索出product表中所有符合40 < Weight < 65的记录。 提示&#xff1a;请使用SELECT语句作答。 表结构: CREATE TABLE product (Pid varchar(20), --商品编号PName varchar(50), --商品名称…