当前位置: 首页 > news >正文

跟我学C++中级篇——单实例和静态化

一、单实例模式

在设计模式中,单实例模式几乎是所有语言中都非常常用的一种设计模式。它在实际的应用中也非常广泛,在很多的开源框架中,都可以看到单实例的影子。单实例,简单的就可以看做在整个应用周期中,只有一个对象的变量。其好处其实就一点,可以集中控制对对象的各种处理(比如优化、内存管理等等),缺点其实就是两个,一个是生命周期无法动态控制;另外一个就是无法动态伸缩。前者容易理解,后者举个简单例子,如果想同时连接多个数据库,这就不好控制了。

二、静态方法和静态变量

学习C/C++语言的,对静态变量和静态方法都是很熟悉的。静态化和单实例也有着千丝万缕的关系,在实现单实例的发展过程中,有很多种方式,现在比较常见的基本就是两种,一种是使用函数的局部静态变量,一种是使用std::call_once,而且这两个都需要从C++0x开始支持。
首先说明一点,此处不是分析如何实现单实例,所以不会对实现的各种方式进行分析说明,重点在于单实例与静态化的关系这一点进行深入剖析。为什么单实例中对静态化情有独钟呢?可不可以全部使用静态化来实现单实例呢?
答案其实反复回答过,静态变量可以防止反复检测(比如经典的Double Check)的性能损失(函数的局部静态变量仍然会有一个检测过程,性能仍然会有些损失),至于能不能使用全部静态化来实现单实例,当然是没有问题的。但问题在于,使用这种方式,会丧失一定的灵活性,这个在下面分进行分析。

三、单实例中的静态化

那么单实例中使用静态化操作有什么优势呢?
1、线程安全性
熟悉全局和静态变量的开发者都有一个头疼的地方,编译器是无法保证多个文件内的相关这样的变量的初始化顺序的。这就出现一个非常难受的问题,如果以后扩展需要多个文件(或者多个库)内的全局或者静态变量需要互相依赖,有可能会出一些让人想象不到的问题。有大牛提出过,把全局或者静态变量搞到一个文件中,可实际场景中,算法保密甚至第三方库都使开发者无法达到这样的目的。
而Meyers’ Singleton即Scott Meyers最早提出来的C++单例模式的写法,其实就是局部静态变量的方式来实现,不过在前面也提到了,它需要C++0x做保证,同样,在一些编译器上,可能也有一些具体的问题,但这不是讨论的范畴了。
2、接口继承
如果使用单实例封装使用静态化,那么就可以实现继承来延续静态化的应用。这其实是一个非常重要的应用,可以继承,意味着可扩展性极大的增强,即灵活性的增加。

3、延迟加载
所谓延迟加载,其实就是懒汉模式,它只会在第一次用到时创建这个对象。这在一些资源要求严格的场景下,还是很有用处的。
4、解决了多文件(库)的互相引用问题
其实这点还是静态变量的初始化顺序导致的问题,这个非常重要,可能很多人都没遇到过,但经验表明,一旦出现这个问题,简直就是一场灾难,因为正常的思维情况下很少考虑这种情况。当你弄明白是这个原因后,会陷入无比的自责和自馁中。

5、生命周期
单实例封装静化,可以主动控制生命周期,这与使用一个单纯的静态或者全局变量有着可控的优势。毕竟全局(静态)变量一旦生成,就是整个进程的生命周期陪伴着,这对于一些对资源要求苛刻的场景下,还是很在裨益的。

另外,单实例的参数传递(非常大的应用程序中)以及后期对测试的支持,都可以做为一种优势来进行说明。但重点是静态化使用与单实例中,如何最具有优势,这才是开发者需要首先考虑的。

下面给出一个Meyers’ Singleton例子:

struct Singleton
{static Singleton &instance(){static Singleton s;return s;} // instanceSingleton(const Singleton &) = delete;Singleton & operator = (const Singleton &) = delete;private:Singleton() {}~Singleton() {}}; // struct Singleton
struct OwnerSingleton:public Singleton
{};

不过一般来说,可能对绝大多数程序员来说,实际情况中遇到单例继承的情况极为罕见吧。
其实直接使用全局或者静态变量与使用单实例,从开发的本质来说,区别不大,但单实例更好的解决了在上层逻辑上的灵活扩展性,这其实就是设计的意义,也是设计模式的意义。实现功能可能大家都会,可如何做得更好,就见仁见智了。

四、总结

到最后,总结各种经验其实可以发现,在实际的应用场景上,使用一些习惯用法或者说设计模式的目的,主要是为了扩展性和防御性编程。如果能够明确的知道不会发生或者某些异常会被阻止的情况下,不进行使用其实也是没问题的(话只能说到这儿,大家自己考虑)。说这些话的目的就是,经验是个好东西,但不要陷入经验主义,书本是个好东西,不要陷入本本主义。实践是检验真理的唯一标准,抓住老鼠的一定是好猫。

相关文章:

跟我学C++中级篇——单实例和静态化

一、单实例模式 在设计模式中,单实例模式几乎是所有语言中都非常常用的一种设计模式。它在实际的应用中也非常广泛,在很多的开源框架中,都可以看到单实例的影子。单实例,简单的就可以看做在整个应用周期中,只有一个对…...

下载 axios.js 文件到本地【linux】

方式一 npm install axios在$NODE_PATH/node_modules/axios/dist路径下即可找到axios.js。 方式二 1、百度搜索 GitHub 官网:https://github.com/ 2、搜索 axios 3、点击 axios/axios 4、下载到本地 5、解压,进入到 dist 文件夹** 参考&#x…...

一些matlab的常用用法。在MATLAB中,如何实现数据的导入和导出?

一些matlab的常用用法。 MATLAB(Matrix Laboratory)是一款广泛使用的数值计算环境和编程语言,主要用于算法开发、数据可视化、数据分析以及数值计算等。以下是一些MATLAB的常用用法: 创建矩阵: 使用方括号 [] 创建矩阵…...

数学建模【插值与拟合】

一、插值与拟合简介 在数学建模过程中,通常要处理由试验、测量得到的大量数据或一些过于复杂而不便于计算的函数表达式,针对此情况,很自然的想法就是,构造一个简单的函数作为要考察数据或复杂函数的近似。插值和拟合就可以解决这…...

汽修专用产品---选型介绍 汽修示波器 汽车示波器 汽车电子 汽修波形 汽车传感器波形 汽车检测

为了满足汽车电子用户的测量需求,我司特推出汽修专用版示波器,一键测量,轻松找出汽车问题。 LOTO各种型号的示波器其实都可以用作汽车传感器信号波形的检测。汽修应用中,工程师对示波器的性能要求对于LOTO产品来说不算高。 在我们…...

如何将简历项目部署到自己的域名下

通过上一篇文章我们得知如何在Github上Fork项目到自己账号下,还有学会配置好简历项目并部署上线,接下来我们就来看一下该项目是如何部署到自己的域名下的 👇 在项目文档中可以看到该简历项目是部署在Vercel上的,首先打开Vercel的官…...

Redisson - 实现Java的Redis分布式和可扩展解决方案

Redisson - 实现Java的Redis分布式和可扩展解决方案 引言: 在现代的分布式系统中,缓存和数据存储扮演着至关重要的角色。Redis作为一种高性能的键值存储数据库,被广泛用于缓存、消息队列、实时数据分析等场景。然而,原生的Redis…...

如何利用EXCEL批量插入图片

目录 1.excel打开目标表格; 2.点开视图-宏-录制宏,可以改宏的名字或者选择默认; 3.然后点开视图-宏-查看宏 4.点编辑进去 5.修改代码: (1)打开之后会显示有一堆代码 (2)将这个…...

django rest framework 学习笔记-实战商城3

01用户模块模型定义_哔哩哔哩_bilibili 本博客借鉴至大佬的视频学习笔记 用户模块及商品数据表结构设计 from ckeditor.fields import RichTextField # pip install django-ckeditor from django.db import models# Create your models here. # from wx.richtext import Ri…...

WPF真入门教程29--MVVM常用框架之MvvmLight

1、MVVM模式回顾 关于mvvm模式的基础知识,请看这2个文章: WPF真入门教程23--MVVM简单介绍 WPF真入门教程24--MVVM模式Command命令 做过VUE开发或微信小程序开发的伙伴,就知道MVVM模式,核心就是数据驱动控件,全栈开…...

QT-Day4

思维导图 作业&#xff1a; 头文件 #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QMessageBox> #include <QTimerEvent>//定时器事件类 #include <QTime> #include <QDebug> #include <QPushButton> #include <QT…...

代码随想录算法训练营第三天

● 自己看到题目的第一想法 203.移除链表元素 方法一&#xff1a; 思路&#xff1a; 设置虚拟头节点 dummyhead 设置临时指针 cur 遍历 整个链表 循环&#xff1a; 如果 cur !nullptr &&cur->next !nullptr 则 遍历链表 否则结束遍历 如果 cur->next val 则…...

蓝桥杯刷题1

目录 1. 平方和 2. 门牌制作 3. 卡片 4. 分数 5. 星期一 6. 顺子日期 1. 平方和 题目描述&#xff1a;小明对数位中含有2、0、1、9 的数字很感兴趣&#xff0c;在1 到40 中这样的数包 括1、2、9、10 至32、39 和40&#xff0c;共28 个&#xff0c;他们的和是574&#x…...

前端学习---- 前端HTML基本元素的介绍

一&#xff1a;显示相关的HTML基础知识 1. 推荐的前端编写工具 2. VScode的html速写规则&#xff08;从a标签开始再用&#xff09; ①、&#xff01;&#xff1a;代表生成html的基本框架元素 ②、html元素&#xff1a;直接书写html,不需要加<>,按回车会自动生成 ③、{}…...

力扣思路题:丑数

此题的思路非常奇妙&#xff0c;可以借鉴一下 bool isUgly(int num){if(num0)return false;while(num%20)num/2;while(num%30)num/3;while(num%50)num/5;return num1; }...

C# this关键字的作用

在C#中&#xff0c;this 关键字有以下几种主要作用&#xff1a; 引用当前对象&#xff1a;this 用于引用当前类的实例。可以通过 this 关键字来访问当前对象的成员变量、方法和属性。 class MyClass {private int myVar;public void SetVar(int var){this.myVar var; // 使用…...

Ubuntu18.04虚拟机磁盘扩容-lvm

Ubuntu18.04虚拟机磁盘扩容-lvm 前提虚拟机虚拟磁盘扩容使用新增的磁盘空间扩展vg和lv 前提 没有虚拟机快照虚拟磁盘不是一次性分配空间其它会影响扩容的前置条件 虚拟机虚拟磁盘扩容 此部分不做详细说明。 使用新增的磁盘空间 此节有两种办法&#xff0c;第一种是将新增的…...

低代码开发:数字赋能智能制造的未来

随着数字化转型的深入推进&#xff0c;智能制造已经成为我国制造业发展的重要方向。在这个过程中&#xff0c;低代码开发作为一种高效、便捷的编程方式&#xff0c;正逐渐成为企业数字化转型的得力助手。本文将探讨低代码开发在智能制造领域的应用及价值。 智能制造的挑战 随着…...

janus-gateway的videoroom插件的RTP包录制功能源码详解

引: janus-gateway在配置文件设置后&#xff0c;可以实现对videoroom插件的每个publisher的音频&#xff0c;视频&#xff0c;数据的RTP流录制成mjr文件。 对于音频&#xff0c;视频的mjr文件&#xff0c;可以使用自带的postprocessing工具janus-pp-rec转成mp4文件。 每个pu…...

nginx+keepalived实现nginx高可用集群以及nginx实现Gateway网关服务集群

一、前言 1、简介 Nginx作为一款高性能的Web服务器和反向代理服务器&#xff0c;被广泛使用。且现如今很多高并发场景需要后端服务集群部署&#xff0c;因此nginx也需要支持集群部署从而避免单点故障的问题。 本文将详细介绍使用 KeepalivedNginx 来实现Nginx的高可用集群和N…...

RocketMQ延迟消息机制

两种延迟消息 RocketMQ中提供了两种延迟消息机制 指定固定的延迟级别 通过在Message中设定一个MessageDelayLevel参数&#xff0c;对应18个预设的延迟级别指定时间点的延迟级别 通过在Message中设定一个DeliverTimeMS指定一个Long类型表示的具体时间点。到了时间点后&#xf…...

定时器任务——若依源码分析

分析util包下面的工具类schedule utils&#xff1a; ScheduleUtils 是若依中用于与 Quartz 框架交互的工具类&#xff0c;封装了定时任务的 创建、更新、暂停、删除等核心逻辑。 createScheduleJob createScheduleJob 用于将任务注册到 Quartz&#xff0c;先构建任务的 JobD…...

微信小程序 - 手机震动

一、界面 <button type"primary" bindtap"shortVibrate">短震动</button> <button type"primary" bindtap"longVibrate">长震动</button> 二、js逻辑代码 注&#xff1a;文档 https://developers.weixin.qq…...

在WSL2的Ubuntu镜像中安装Docker

Docker官网链接: https://docs.docker.com/engine/install/ubuntu/ 1、运行以下命令卸载所有冲突的软件包&#xff1a; for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do sudo apt-get remove $pkg; done2、设置Docker…...

Android 之 kotlin 语言学习笔记三(Kotlin-Java 互操作)

参考官方文档&#xff1a;https://developer.android.google.cn/kotlin/interop?hlzh-cn 一、Java&#xff08;供 Kotlin 使用&#xff09; 1、不得使用硬关键字 不要使用 Kotlin 的任何硬关键字作为方法的名称 或字段。允许使用 Kotlin 的软关键字、修饰符关键字和特殊标识…...

服务器--宝塔命令

一、宝塔面板安装命令 ⚠️ 必须使用 root 用户 或 sudo 权限执行&#xff01; sudo su - 1. CentOS 系统&#xff1a; yum install -y wget && wget -O install.sh http://download.bt.cn/install/install_6.0.sh && sh install.sh2. Ubuntu / Debian 系统…...

蓝桥杯 冶炼金属

原题目链接 &#x1f527; 冶炼金属转换率推测题解 &#x1f4dc; 原题描述 小蓝有一个神奇的炉子用于将普通金属 O O O 冶炼成为一种特殊金属 X X X。这个炉子有一个属性叫转换率 V V V&#xff0c;是一个正整数&#xff0c;表示每 V V V 个普通金属 O O O 可以冶炼出 …...

Java求职者面试指南:计算机基础与源码原理深度解析

Java求职者面试指南&#xff1a;计算机基础与源码原理深度解析 第一轮提问&#xff1a;基础概念问题 1. 请解释什么是进程和线程的区别&#xff1f; 面试官&#xff1a;进程是程序的一次执行过程&#xff0c;是系统进行资源分配和调度的基本单位&#xff1b;而线程是进程中的…...

虚拟电厂发展三大趋势:市场化、技术主导、车网互联

市场化&#xff1a;从政策驱动到多元盈利 政策全面赋能 2025年4月&#xff0c;国家发改委、能源局发布《关于加快推进虚拟电厂发展的指导意见》&#xff0c;首次明确虚拟电厂为“独立市场主体”&#xff0c;提出硬性目标&#xff1a;2027年全国调节能力≥2000万千瓦&#xff0…...

【C++进阶篇】智能指针

C内存管理终极指南&#xff1a;智能指针从入门到源码剖析 一. 智能指针1.1 auto_ptr1.2 unique_ptr1.3 shared_ptr1.4 make_shared 二. 原理三. shared_ptr循环引用问题三. 线程安全问题四. 内存泄漏4.1 什么是内存泄漏4.2 危害4.3 避免内存泄漏 五. 最后 一. 智能指针 智能指…...