当前位置: 首页 > 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…...

FFmpeg 低延迟同屏方案

引言 在实时互动需求激增的当下&#xff0c;无论是在线教育中的师生同屏演示、远程办公的屏幕共享协作&#xff0c;还是游戏直播的画面实时传输&#xff0c;低延迟同屏已成为保障用户体验的核心指标。FFmpeg 作为一款功能强大的多媒体框架&#xff0c;凭借其灵活的编解码、数据…...

中南大学无人机智能体的全面评估!BEDI:用于评估无人机上具身智能体的综合性基准测试

作者&#xff1a;Mingning Guo, Mengwei Wu, Jiarun He, Shaoxian Li, Haifeng Li, Chao Tao单位&#xff1a;中南大学地球科学与信息物理学院论文标题&#xff1a;BEDI: A Comprehensive Benchmark for Evaluating Embodied Agents on UAVs论文链接&#xff1a;https://arxiv.…...

循环冗余码校验CRC码 算法步骤+详细实例计算

通信过程&#xff1a;&#xff08;白话解释&#xff09; 我们将原始待发送的消息称为 M M M&#xff0c;依据发送接收消息双方约定的生成多项式 G ( x ) G(x) G(x)&#xff08;意思就是 G &#xff08; x ) G&#xff08;x) G&#xff08;x) 是已知的&#xff09;&#xff0…...

在四层代理中还原真实客户端ngx_stream_realip_module

一、模块原理与价值 PROXY Protocol 回溯 第三方负载均衡&#xff08;如 HAProxy、AWS NLB、阿里 SLB&#xff09;发起上游连接时&#xff0c;将真实客户端 IP/Port 写入 PROXY Protocol v1/v2 头。Stream 层接收到头部后&#xff0c;ngx_stream_realip_module 从中提取原始信息…...

P3 QT项目----记事本(3.8)

3.8 记事本项目总结 项目源码 1.main.cpp #include "widget.h" #include <QApplication> int main(int argc, char *argv[]) {QApplication a(argc, argv);Widget w;w.show();return a.exec(); } 2.widget.cpp #include "widget.h" #include &q…...

智能分布式爬虫的数据处理流水线优化:基于深度强化学习的数据质量控制

在数字化浪潮席卷全球的今天&#xff0c;数据已成为企业和研究机构的核心资产。智能分布式爬虫作为高效的数据采集工具&#xff0c;在大规模数据获取中发挥着关键作用。然而&#xff0c;传统的数据处理流水线在面对复杂多变的网络环境和海量异构数据时&#xff0c;常出现数据质…...

并发编程 - go版

1.并发编程基础概念 进程和线程 A. 进程是程序在操作系统中的一次执行过程&#xff0c;系统进行资源分配和调度的一个独立单位。B. 线程是进程的一个执行实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。C.一个进程可以创建和撤销多个线程;同一个进程中…...

python爬虫——气象数据爬取

一、导入库与全局配置 python 运行 import json import datetime import time import requests from sqlalchemy import create_engine import csv import pandas as pd作用&#xff1a; 引入数据解析、网络请求、时间处理、数据库操作等所需库。requests&#xff1a;发送 …...

LCTF液晶可调谐滤波器在多光谱相机捕捉无人机目标检测中的作用

中达瑞和自2005年成立以来&#xff0c;一直在光谱成像领域深度钻研和发展&#xff0c;始终致力于研发高性能、高可靠性的光谱成像相机&#xff0c;为科研院校提供更优的产品和服务。在《低空背景下无人机目标的光谱特征研究及目标检测应用》这篇论文中提到中达瑞和 LCTF 作为多…...

SpringAI实战:ChatModel智能对话全解

一、引言&#xff1a;Spring AI 与 Chat Model 的核心价值 &#x1f680; 在 Java 生态中集成大模型能力&#xff0c;Spring AI 提供了高效的解决方案 &#x1f916;。其中 Chat Model 作为核心交互组件&#xff0c;通过标准化接口简化了与大语言模型&#xff08;LLM&#xff0…...