【C++几种单例模式解读及实现方式】
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
- 前言
- 一、单例是什么?
- 二、解读
- 1.懒汉式
- 2.饿汉式
- 3.static变量特性
- 4.call_once特性
- 总结
前言
单例模式几乎是每种语言都不可少的一种设计模式,今天就针对C++语言来解读下集中单例模式,并给出代码说明。
一、单例是什么?
单例就是单实例,简而言之内存中只存在这一个实例,在很多场景下很有用,比如线程池、内存池等等。
二、解读
按照创建时机可以分为饿汉式和懒汉式。所谓饿汉式就是程序启动的时候立即创建,饿汉式就是需要的时候创建。
1.懒汉式
懒汉式顾名思义,不会主动创建,直到主动获取才创建。懒汉式又主要分为两种,线程安全和线程不安全。接下来分别介绍这几种和提供源代码示例。
简单模式:
class Singleton {static Singleton *getInstance() {if (instance == nullptr) {instance = new Singleton();}return instance;}private:static Singleton *instance;};Singleton *Singleton::instance = nullptr;
优点:性能和饿汉式差不多,没有锁,性能不会损失
缺点:线程不安全
总结:需要自己确保线程安全,比如启动线程前就要创建好,避免竞争条件产生
线程安全:
#include <mutex>
class Singleton {public:static Singleton *getInstance() {std::lock_guard<std::mutex> lock(mtx);if (instance == nullptr) {instance = new Singleton();}return instance;}private:static Singleton *instance;static std::mutex mtx;};Singleton *Singleton::instance = nullptr;std::mutex Singleton::mtx;
优点:线程安全,随时随地都是安全的
缺点:性能差,每次获取实例都要上锁
总结:不建议使用
双重检查锁:
#include <mutex>
class Singleton {public:static Singleton *getInstance() {if (instance == nullptr) {std::lock_guard<std::mutex> lock(mtx);if (instance == nullptr) {instance = new Singleton();}}return instance;}private:static Singleton *instance;static std::mutex mtx;};Singleton *Singleton::instance = nullptr;std::mutex Singleton::mtx;
优点:线程安全,性能比上面的强
缺点:性能有轻微损耗,只有第一次创建才需要上锁,后面访问不需要上锁
总结:强烈推荐,既解决了线程安全问题,又解决了性能问题
2.饿汉式
不会产生数据竞争,程序启动时就创建和,在竞争条件出现之前创建完成,所以先天是线程安全的。
class Singleton {public:static Singleton &getInstance() {return instance;}private:static Singleton instance;};Singleton Singleton::instance;
优点:线程安全,性能最好
缺点:无论需不需要都会创建,会浪费资源
总结:可用但不太推荐
3.static变量特性
C++11之后static修饰的局部变量有一个很重要的特性:初始化的时候会自动加锁,这个特性是编译器负责维护的。所以可以借用这个特性开发一个单例模式,一定是线程安全的,而且提供不俗的性能。
注:这个单例又叫米尔斯单例(Meyers' Singleton)
class Singleton {public:static Singleton &getInstance() {static Singleton instance;return instance;}private:Singleton() {}public:Singleton(const Singleton &) = delete;Singleton &operator=(const Singleton &) = delete;};
优点:线程安全,性能不俗
缺点:初始化上锁略微拖慢性能,后面正常获取,C++11以后版本才行
总结:极其推荐
4.call_once特性
除了米尔斯单例,还有一个C++11的新特性可以设计单例,这个特性我们平常容易忽视,那就是call_once。它也是一种线程同步机制,C++保证call_once保护的方法只被调用一次。
#include <atomic>
class Singleton {public:static Singleton& getInstance(){std::call_once(flag,[]{instance = new Singleton();});return *instance;}private:static Singleton* instance;static std::once_flag flag;};Singleton* Singleton::instance = nullptr;std::once_flag Singleton::flag;
优点:线程安全,性能不俗,针对方法可以同时初始化多个资源
缺点:第一次调用拖慢性能,后面就不会了,C++11以后版本才行
总结:和米尔斯很像,但是实现比米尔斯复杂,推荐指数放在米尔斯单例之后
总结
1、C++11以上版本优先使用米尔斯单例,比双重检查锁性能强
2、其他场景建议双重检查锁,call_once酌情使用
相关文章:
【C++几种单例模式解读及实现方式】
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、单例是什么?二、解读1.懒汉式2.饿汉式3.static变量特性4.call_once特性 总结 前言 单例模式几乎是每种语言都不可少的一种设计模式,…...
QT开发--串口通信
第十六章 串口通信 16.1 串口通信基础 串口通信主要通过DB9接口,适用于短距离(<10米)。关键参数包括: 波特率:每秒传输bit数,如9600。数据位:信息包中的有效数据位数。停止位:…...
数据库(至少还的再花两天 )
1 连接查询 左连接 右连接 2 聚合函数 SQL 统计求和 求最值 count sum avg max min 3 SQL关键字 limit 分页 group by 分组 distinct 去重 4 Select执行顺序 from where group by order by 5 数据库三范式 原子性 唯一性 直接性 6 存储引擎 MyISAM InnoDB 7 …...
网络安全公司及其主要产品介绍
以下是一些全球领先的网络安全公司及其主要产品介绍: 一、思科(Cisco) 思科是全球最大的网络设备供应商之一,其网络安全产品以企业级解决方案为主,覆盖多种安全需求。 Cisco ASA(Adaptive Security Appli…...
orjson:高性能的Python JSON库
在Python中处理JSON数据是一项常见任务,标准库的json模块虽然功能齐全,但在性能方面还有提升空间。今天我要向大家介绍一个出色的第三方JSON库 - orjson。 orjson简介 orjson是一个快速、正确的Python JSON库。它具有以下主要特点: 性能卓越 - 在序列化和反序列化方面都比标准…...
常见几大排序算法
排序算法是计算机科学中的基本算法,它们将一个无序的数组或列表按特定顺序进行排列(如升序或降序)。常见的排序算法可以根据其时间复杂度、空间复杂度和适用场景分类。以下是几种常见的排序算法: 1. 冒泡排序(Bubble …...
Linux下CMake入门
CMake的基础知识 什么是 CMake CMake 是一个跨平台的构建工具,主要用于管理构建过程。CMake 不直接构建项目,而是生成特定平台上的构建系统(如 Unix 下的 Makefile,Windows 下的 Visual Studio 工程),然后…...
网络资源模板--Android Studio 实现简易记事本App
目录 一、项目演示 二、项目测试环境 三、项目详情 四、完整的项目源码 一、项目演示 网络资源模板--基于Android studio 实现的简易记事本App 二、项目测试环境 三、项目详情 首页 创建一个空的笔记本列表 mNotebookList。使用该列表和指定的布局资源 item_notebook 创建…...
根据Vue对比来深入学习React 下 props 组件传值 插槽 样式操作 hooks 高阶组件 性能优化
文章目录 函数组件的特点props组件间的传值父传子看上例子传父兄弟组件传值祖先组件传值 插槽基础插槽具名插槽作用域插槽 样式操作**CSS Modules** 生命周期useRef常用hookuseStateuseEffectuseContextuseReduceruseMemouseCallback 高阶组件什么时候使用 react性能问题和优化…...
HTML(六)超链接
HTML讲解(一)body部分_html body-CSDN博客 <!DOCTYPE html> <html><head><meta charset"UTF-8" /><title>title</title> </head><body><a href"https://blog.csdn.net/2301_8034953…...
【Coroutines】Implement Lua Coroutine by Kotlin - 2
Last Chapter Link 文章目录 Symmetric CoroutinesNon-Symmetric Coroutine SampleSymmetric Coroutine SampleHow to Implement Symmetric CoroutinesWonderful TricksCode DesignTail Recursion OptimizationFull Sources Symmetric Coroutines in last blog, we have talk…...
java计算机毕设课设—扫雷游戏(附源码、文章、相关截图、部署视频)
这是什么系统? 资源获取方式再最下方(本次10月份活动福利,免费提供下载,自行到对应的方式1下载,csdn的0积分下载) java计算机毕设课设—扫雷游戏(附源码、文章、相关截图、部署视频) 基于Java的扫雷游戏…...
AndroidLogger 使用问题
Q1:解压zip后,启动Notepad未看到AndroidLogger工具栏 请检查plugins下安装位置是否正确,必须与下图一致,再确认Notepad 是否为 x64 ? Q2:使用 adb 可以显示已连接,但是获取不到日志 暂时不确定问…...
数据库常见面试
8道面试题 目录 目录 7道面试题 1.怎样进行sql优化 4、group by优化 5、limit优化 6、count优化 7、update优化 2.。怎样查看sql执行情况呢(哪个关键字),说说你对这个关键字的认识 4) possible_key: 5) key 3.说说你对innodb和 myisam的理解 …...
boxplot 绘制箱线图,添加数据点
先看效果图 import matplotlib.pyplot as plt #! 解决不显示的问题:中文设置为宋体格式 plt.rcParams[font.family] ["Times New Roman", SimSun]def plot_boxplot(data_list, out_file, x_custom_labels):# 画图fig, ax plt.subplots(figsize(90, 6…...
用sdkman管理多个jdk切换
前言 最近项目前后端进行升级,需要在jdk8和jdk17两个版本切换。最简单的是通过手动切换,但切换过程太繁琐,修改环境变量,达到切换目的。于是尝试其它解决方案,最终确实使用sdkman工具。 sdkman 是一款面向Java开发者的…...
【AIGC】ChatGPT提示词Prompt高效编写模式:结构化Prompt、提示词生成器与单样本/少样本提示
💯前言 在如今AI技术迅猛发展的背景下,尽管像ChatGPT这样的大型语言模型具备强大的生成能力,但它们的输出质量有时仍难以完全满足我们的预期。为了让ChatGPT生成更加准确、可靠的内容,掌握高效的Prompt编写技巧变得尤为重要。本文…...
反调式实战(有道翻译窗口弹出)
1.添加脚本断点实现源码获取 2.Function构造器构造debugger 因为是窗口被弹出的情况,所以window.closefunction()构造debugger。 3.定位到影响弹出的JavaScript代码片段 反调试思想:置空和替换,所以将其JavaScript进行注释或者删除。 这里主…...
verilog端口使用注意事项
下图存在组合逻辑反馈环,即组合逻辑的输出反馈到输入(赋值的左右2边存在相同的信号),此种情况会造成系统不稳定。比如在data_in20的情况下,在data_out0 时候,输出的数据会反馈到输入,输入再输出,从而造成不…...
Docker常用命令大全汇总
Docker是一种流行的容器化平台,可以在一个独立的、隔离的环境中构建、部署和运行应用程序。了解Docker常用命令可以帮助我们更高效地管理容器,快速开发和部署应用。本文将整理一系列Docker的常用命令,便于日常使用和学习。 1 Docker基础命令 1.1 启动/停止/重启docker # …...
第19节 Node.js Express 框架
Express 是一个为Node.js设计的web开发框架,它基于nodejs平台。 Express 简介 Express是一个简洁而灵活的node.js Web应用框架, 提供了一系列强大特性帮助你创建各种Web应用,和丰富的HTTP工具。 使用Express可以快速地搭建一个完整功能的网站。 Expre…...
Go 语言接口详解
Go 语言接口详解 核心概念 接口定义 在 Go 语言中,接口是一种抽象类型,它定义了一组方法的集合: // 定义接口 type Shape interface {Area() float64Perimeter() float64 } 接口实现 Go 接口的实现是隐式的: // 矩形结构体…...
Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility
Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility 1. 实验室环境1.1 实验室环境1.2 小测试 2. The Endor System2.1 部署应用2.2 检查现有策略 3. Cilium 策略实体3.1 创建 allow-all 网络策略3.2 在 Hubble CLI 中验证网络策略源3.3 …...
微信小程序云开发平台MySQL的连接方式
注:微信小程序云开发平台指的是腾讯云开发 先给结论:微信小程序云开发平台的MySQL,无法通过获取数据库连接信息的方式进行连接,连接只能通过云开发的SDK连接,具体要参考官方文档: 为什么? 因为…...
多种风格导航菜单 HTML 实现(附源码)
下面我将为您展示 6 种不同风格的导航菜单实现,每种都包含完整 HTML、CSS 和 JavaScript 代码。 1. 简约水平导航栏 <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport&qu…...
【碎碎念】宝可梦 Mesh GO : 基于MESH网络的口袋妖怪 宝可梦GO游戏自组网系统
目录 游戏说明《宝可梦 Mesh GO》 —— 局域宝可梦探索Pokmon GO 类游戏核心理念应用场景Mesh 特性 宝可梦玩法融合设计游戏构想要素1. 地图探索(基于物理空间 广播范围)2. 野生宝可梦生成与广播3. 对战系统4. 道具与通信5. 延伸玩法 安全性设计 技术选…...
使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台
🎯 使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台 📌 项目背景 随着大语言模型(LLM)的广泛应用,开发者常面临多个挑战: 各大模型(OpenAI、Claude、Gemini、Ollama)接口风格不统一;缺乏一个统一平台进行模型调用与测试;本地模型 Ollama 的集成与前…...
Python ROS2【机器人中间件框架】 简介
销量过万TEEIS德国护膝夏天用薄款 优惠券冠生园 百花蜂蜜428g 挤压瓶纯蜂蜜巨奇严选 鞋子除臭剂360ml 多芬身体磨砂膏280g健70%-75%酒精消毒棉片湿巾1418cm 80片/袋3袋大包清洁食品用消毒 优惠券AIMORNY52朵红玫瑰永生香皂花同城配送非鲜花七夕情人节生日礼物送女友 热卖妙洁棉…...
MySQL 部分重点知识篇
一、数据库对象 1. 主键 定义 :主键是用于唯一标识表中每一行记录的字段或字段组合。它具有唯一性和非空性特点。 作用 :确保数据的完整性,便于数据的查询和管理。 示例 :在学生信息表中,学号可以作为主键ÿ…...
OD 算法题 B卷【正整数到Excel编号之间的转换】
文章目录 正整数到Excel编号之间的转换 正整数到Excel编号之间的转换 excel的列编号是这样的:a b c … z aa ab ac… az ba bb bc…yz za zb zc …zz aaa aab aac…; 分别代表以下的编号1 2 3 … 26 27 28 29… 52 53 54 55… 676 677 678 679 … 702 703 704 705;…...
