【C++】C++的单例模式、跟踪内存分配的简单方法

二十四、C++的单例模式、跟踪内存分配的简单方法

1、C++的单例模式
本小标题不是讨论C++的语言特性,而是一种设计模式,用于确保一个类在任何情况下都只有一个实例,并提供一个全局访问点来获取这个实例。即C++的单例模式。这种模式常用于资源管理,如‌线程池、‌缓存、‌日志对象等,以确保这些关键资源不会被过度使用,同时节省内存。单例模式的核心在于类自身负责创建自己的唯一实例,并提供一个静态方法来获取这个实例,从而防止外部代码创建多个实例。‌

(1)关于单例模式的一点说明:
单例模式说白了就是,我只想有一个对象的单一实例。也就是只想有一个对象的单一的数据集,比如一些专属它的变量,和一些仅针对它的函数。当然这些函数也是仅仅针对这个对象的、特定的数据集的操作。
那么,要实现单例模式,至少有下面三种实现途径:
一是用类来实现。像Java和C#它们天生就是面向对象语言,所以它们强制你使用类。特别是java,所有东西都必须是一个类,你不能在类之外有代码,如果你想要静态的功能,你不需要实例化,但你必须在你的类中创建静态成员。
二是可以用命名空间来实现。C++不像Java和C#那么多规则限制,C++不对静态函数做这些规则限制,所以C++可以不需要写一个类,可以在某个名称空间中写一些函数,甚至在全局名称空间中,它们不属于任何类的类型。其实说白了,类名就是一种命名空间。用类来实现单例模式,从根本上说,就是将类用作命名空间,来调用某些函数。
三是,C++可以有完全全局的变量,或者可以有一个静态变量,它被绑定到一个特定的翻译单元,或者一个特定的CPP文件。也是可以实现单例模式的。

所以要实现单例模式并不一定非得用类来实现,只是用类实现是最简单直观的。

(2)单例设计模式在哪里发挥作用呢?
当我们想要拥有应用于某种全局数据集的功能,而且我们只是想要重复使用时,单例是非常有用的。比如一个随机数生成器,我们只是希望能够查询它,比如给我们一个随机数,我们不需要实例化它,遍历所有东西。因为我们只是想实例化它一次,这样它就会生成随机数生成器的种子,建立起它所需要的任何辅助的东西了。然后我们要调用一个函数,基于我们初始化它的结果,它会给我们一个随机数。
另一个很好的例子是渲染器,渲染器通常是一个非常全局的东西。我们通常不会有一个渲染器的多个实例,我们有一个渲染器,我们向它提交所有这些渲染命令,然后它会为我们渲染一些东西。如果我们将其分解到opengl的部分,我们实际上通过渲染器调用opengl调用的东西,本身就是一组全局函数。这根本不是和某种对象有关的东西,它们只是C风格的函数,没有类,一点关系都没有。

‌‌(3)用类实现单例模式的几个关键点:
发明类的初心就是重复使用,创建任意个实例的,但是现在我们只允许它只能有一个实例,所以我们要通过下面几点来达到目的:
一是私有构造函数‌:防止外部通过new操作符创建多个实例,因为new操作符的底层也是调用构造函数,私有构造函数就无法调用。
‌‌二是使用静态变量‌存储类的唯一实例。
‌三是使用公共静态方法‌提供一个全局访问点来获取这个实例。

下面编写一个非常非常基本的、用类来实现单例的例子:

这段代码通过将构造函数设为私有,确保外部无法直接创建实例;创建一个自身的实例,并静态的、私有的存储;然后通过一个公共的静态方法来获取那个实例。这些操作就让这个类成了一个单例类。

可见,C++中的类单例只是一种组织一堆全局变量和静态函数的方式,这些静态函数有时可能对这些变量起作用,有时也可能不对这些变量起作用。也就是在一个单一的名称空间下(类名),把这些全局变量和静态函数组织在一起。这就是C++类单例的本质

如果还是不是太理解的同学可以参考我之前写的博文 【C++】类、静态static、枚举、重载、多态、继承、重写、虚函数、纯需函数、虚析构函数_静态与多态:重写、重载、模板-CSDN博客 中的static部分,相信看完就明白了。

如果觉得上面的例子没有啥意义,那我们利用单例类写一个随机数生成器:

这个随机数生成器是我们在一开始就放入了随机数种子,然后在整个程序中重用,非常简单,因为我们不需要一个随机数生成器有多个实例。上图单例仅仅是返回了一个静态值,所以这个单例可以写成右边的静态函数。但是我们还是使用了类单例(左图),因为类单例之所以为类单例,是因为它实际上还是一个类,因此它可以支持所有的类特性,比如类成员变量等。

如果说上面需要调用GetInstance再调用get_seed很麻烦,我们可以这样改写:

如果说上面的写法还是特别麻烦,我们还可以这样写:

此时左图的写法就清晰很多,不需要像右图那样,三步分散得到处都是,可读性比较差。

结论:单例的核心就是上面的GetInstance函数。单例的声明周期就是你的应用的生命周期。一旦我有了这个单例,我可以写任何数量的非静态方法,都可以通过GetInstance函数访问这些方法。

下面再简单展示一下使用命名空间实现的写法:

虽然使用命名空间也可以实现,但是失去了public、private这些类的功能。

2、跟踪内存分配的简单方法
如何跟踪内存的分配?这个知识点其实前面都已经有过涉及,这里就是进行一个小结。

知道你的程序什么时候分配内存,特别是堆内存,是非常有用的。尤其是在性能关键的代码中,在堆上分配内存是很糟糕的做法。 如果你知道是哪行代码分配了内存,你就可以针对性的优化你的程序,使其运行得更快。此外,如果你能看到内存被分配到哪里,可以帮助你更好的理解你的代码的工作原理。所以本部分要编写代码跟踪应用程序内存的总体使用情况,而不是依赖某些内存管理工具。


所以,我们可以通过在operator new函数中插入一个断点,就可以精确的追踪这些内存分配的来源。

下面写一个完整的new和delete:

我们还可以维护一个allocation metrics,就可以确切知道有多少内存被使用,有多少内存被分配,有多少内存被释放等等:

当然上面这个可能写得比较牵强,anyway大体就是这么写的。

最后提一下,VS内置的内存分配跟踪分析工具Valgrind,是一款用于内存调试、内存泄露检测以及性能分析的软件开发工具。自己写还是使用现有的工具,这个你自己看着办吧。

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

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

相关文章

掌握鸿蒙生态的崛起之机:开发者的挑战与机遇

掌握鸿蒙生态的崛起之机:开发者的挑战与机遇 引言 在智能设备领域,鸿蒙系统(HarmonyOS)正迅速崛起,与安卓、iOS形成三足鼎立之势。作为一名开发者,如何抓住这一机遇,解决开发中的挑战&#xf…

任务中心全新升级,新增分享接口文档功能,MeterSphere开源持续测试工具v3.4版本发布

2024年11月5日,MeterSphere开源持续测试工具正式发布v3.4版本。 在这一版本中,系统设置方面,任务中心支持实时查看系统即时任务与系统后台任务;接口测试方面,新增接口文档分享功能、接口场景导入导出功能,…

Python毕业设计选题:基于django+vue的荣誉证书管理系统

开发语言:Python框架:djangoPython版本:python3.7.7数据库:mysql 5.7数据库工具:Navicat11开发软件:PyCharm 系统展示 管理员登录 管理员功能界面 学生管理 教师管理 证书分类管理 荣誉证书管理 菜单列表…

Ubuntu下如何管理多个ssh密钥

Ubuntu下如何管理多个ssh密钥 前言 ‍ 我一直在逃避这个问题,误以为我能够单纯地用一个 ssh 走天下。 好吧,现实是我不得不管理多个 ssh 做,那就写个博客总结一下吧。 查阅后发现前人已经总结了不少,那我就结合之后&#xff…

Pr 视频过渡:沉浸式视频

效果面板/视频过渡/沉浸式视频 Video Transitions/Immersive Video Adobe Premiere Pro 的视频过渡效果中,沉浸式视频 Immersive Video效果组主要用于 VR 视频剪辑之间的过渡。 自动 VR 属性 Auto VR Properties是所有 VR 视频过渡效果的通用选项。 默认勾选&#x…

mongoDB的安装及使用

mongodb的安装可参考:Centos系统中mongodb的安装详解_centos安装mongodb-CSDN博客 不要下载最新的版本,新的版本中mongo命令无法使用,也就是安装后不能通过mongo命令登录,我这里使用5.0.30版本; mongodb安装成功后通过…

SDL事件相关

文章目录 事件相关的函数和数据结构用户自定义事件代码相关: 事件相关的函数和数据结构 SDL_WaitEvent :等待一个事件SDL_PushEvent 发送一个事件SDL_PumpEvents(): 将硬件设备产生的时间放入事件队列 ,用于读取事件,在调用该函数之前&#…

SpringBoot框架在资产管理中的应用

3系统分析 3.1可行性分析 通过对本企业资产管理系统实行的目的初步调查和分析,提出可行性方案并对其一一进行论证。我们在这里主要从技术可行性、经济可行性、操作可行性等方面进行分析。 3.1.1技术可行性 本企业资产管理系统采用Spring Boot框架,JAVA作…

华为私有接口类型hybrid

华为私有接口类型hybrid Tip&#xff1a;hybrid类型&#xff0c;简称混合型接口。 本次实验模拟2层网络下 vlan10 vlan20 不能互访&#xff0c;vlan10 vlan20 同时可以访问vlan100 sw1配置如下&#xff1a; <Huawei>sy [Huawei]sys sw1 [sw1]vl ba 10 20 100 [sw1]int…

前端 性能优化 (图片与样式篇)

文章目录 前端能够做哪些图片优化?1、减小图片体积2、图片缓存服务工作线程 (Service Workers)缓存IndexDB缓存图片LocalStorage缓存 3、图片懒加载使用 loading"lazy" 属性 4、不同分辨率下使用不同的图片5、使用webp格式的图片6、配置图片CDN7、减少图片和动图的使…

Spring Boot实现多数据源连接和切换

文章目录 前言一、多数据源配置与切换方案二、实现步骤1. 创建多个 DataSource 配置类2. 创建 DataSource 配置类3. 创建动态数据源路由类4. 实现 DynamicDataSource 类5. 创建 DataSourceContextHolder 来存储当前的数据源标识6. AOP 方式切换数据源7. 自定义注解来指定数据源…

【023】基于51单片机数字电压表

☆、设计硬件组成&#xff1a;51单片机最小系统ADC0832模数转换LCD1602液晶显示。 1、本设计采用STC89C51/52、AT89C51/52、AT89S51/52单片机作为主控芯片&#xff1b; 2、采用LCD1602液晶显示屏实时更新显示所测量的电压值&#xff1b; 3、采用ADC0832进行采集电压信号&…

ElasticSearch从环境搭建到如何使用的全过程

ES是什么? ES是一款非常强大的开源的高扩展的分布式全文检索引擎,可以帮助我们从海量数据中快速找到需要的内容,它可以近乎实时的存储、检索数据。还可以实现日志统计、分析、系统监控等功能。 例如京东、淘宝、头条等站内搜索功能 在大数据环境下&#xff0c;Elasticsearc…

SpringCloud框架学习(第一部分:初始项目搭建)

目录 一、SpringBoot和SpringCloud版本选型 1.Springcloud版本选择 2.Springcloud版本选择 3.Springcloud Alibaba版本选择 4.SpringCloud VS SpringBoot VS SpringCloud Alibaba版本三者制约对应关系 二、SpringCloud介绍 1.单体架构 2.微服务架构 3.springcloud 4.S…

uni-app打包后报错云服务空间未关联

使用uni-app打包到h5 项目里面用到了uni-app的云端一体城市选择组件&#xff0c;这个组件数据用到了uniCloud云服务空间&#xff0c;在本地运行没问题&#xff0c;打包之后测试环境报错&#xff1a; 一顿查&#xff0c;查到了官网是这样说的&#xff1a; cli publish --platfo…

解决Mac M芯片 Wireshark 运行rvictl -s 后,出现Starting device failed

前言 mac os big sur 之后&#xff0c;苹果系统的安全性能提升&#xff0c;导致 rvictl -s 创建虚拟网卡失败。 $ rvictl -s 000348120-001621w21184C01E bootstrap_look_up(): 1102Starting device 000348120-001621w21184C01E [FAILED] 这是由于 rvictl 需要开启系统扩展才能…

公共命名空间:内置名

使用方言[Perl] 使用[哇哇小可爱的方言] 第一句明确指出了使用什么&#xff0c;使用方言&#xff1b; 第二句也是使用方言的意思。 如果中括号里的内容&#xff0c;完全当做参数来处理&#xff0c;那么&#xff0c;第二句就难以确定使用什么。这里需要使用叫做“内置名”的技术…

浙江酒店WIFI广告路由实现——酒店经营

像这样的链接WIFI&#xff0c;后自动弹出连接认证&#xff0c;或者广告&#xff0c;可以展示酒店介绍&#xff0c;住房信息 智能wifi优点&#xff1a; 对于酒店体验而言&#xff1a; 1. 便捷性&#xff1a;客人无需繁琐的认证步骤就能自动连接 WiFi&#xff0c;提升了入住的便…

音视频入门基础:H.264专题(22)——通过FFprobe显示H.264裸流每个packet的信息

音视频入门基础&#xff1a;H.264专题系列文章&#xff1a; 音视频入门基础&#xff1a;H.264专题&#xff08;1&#xff09;——H.264官方文档下载 音视频入门基础&#xff1a;H.264专题&#xff08;2&#xff09;——使用FFmpeg命令生成H.264裸流文件 音视频入门基础&…

JavaScript中执行上下文和执行栈是什么?

一、执行上下文 简单的来说&#xff0c;执行上下文是一种对Javascript代码执行环境的抽象概念&#xff0c;也就是说只要有Javascript代码运行&#xff0c;那么它就一定是运行在执行上下文中 执行上下文的类型分为三种&#xff1a; 全局执行上下文&#xff1a;只有一个&#…