【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,一经查实,立即删除!

相关文章

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

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

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

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

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…

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 需要开启系统扩展才能…

浙江酒店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;只有一个&#…

达梦8-达梦数据实时同步软件(DMHS)配置-Oracle-DM8

1、安装环境 源端目的端IP地址192.168.6.111192.168.6.110系统版本Red Hat 6.4Kylin v10数据库版本Oracle11g达梦 v8系统用户Oracledmdba字符集MERICAN_AMERICA.AL32UTF8UTF-8端口15215236实例名PRODDMSERVER数据库软件目录/u01/app/oracle/opt/dmdbmsDMHS安装目录/u01/dmhs/o…

【优选算法 — 滑动窗口】滑动窗口小专题(一)

长度最小的子数组 长度最小的子数组 题目解析&#xff1a; 对于示例一 对于剩下两种示例&#xff1a; 解法一&#xff1a;暴力枚举 把所有的子数组全部枚举出来&#xff0c;并且枚举出的每一个子数组求和判断&#xff0c;返回长度最小的子数组&#xff1b; 时间复杂度 &…

【数据集】【YOLO】【目标检测】安全帽识别数据集 22789 张,YOLO安全帽佩戴目标检测实战训练教程!

数据集介绍 【数据集】安全帽识别数据集 22789 张&#xff0c;目标检测&#xff0c;包含YOLO/VOC格式标注。数据集中包含2种分类&#xff1a;{0: head, 1: helmet}&#xff0c;分别是无安全帽和佩戴安全帽。数据集来自国内外图片网站和视频截图。检测场景为施工地工人安全帽佩…

Linux 系统结构

Linux系统一般有4个主要部分&#xff1a;内核、shell、文件系统和应用程序。内核、shell和文件系统一起形成了基本的操作系统结构&#xff0c;它们使得用户可以运行程序、管理文件并使用系统。 1. linux内核 内核是操作系统的核心&#xff0c;具有很多最基本功能&#xff0c;它…

飞书 富文本(Markdown)

飞书机器人webhook支持Markdown格式&#xff0c;包括表格 表格 |Syntax | Description |\n|-------- | -------- |\n|Header | Title |\n|Paragraph | Text |参考 富文本&#xff08;Markdown&#xff09;

R语言实战——一些批量对地理数据进行操作的方法

各位朋友在进行数据处理时&#xff0c;当有多张栅格影像时&#xff0c;如果我们都要进行同一操作时&#xff0c;一张一张做很繁琐&#xff0c;用ArcGIS模型构建器是一种比较好的方法。当然&#xff0c;今天小编新学了R语言上面进行批量裁剪&#xff0c;一起来学习一下吧&#x…