C++语法(26)--- 特殊类设计
C++语法(25)--- 异常与智能指针_哈里沃克的博客-CSDN博客
https://blog.csdn.net/m0_63488627/article/details/131537799?spm=1001.2014.3001.5501
目录
1.特殊类设计
1.设计一个类,不能被拷贝
C++98
C++11
2.设计一个类,只能在堆上创建对象
1.封掉所有拷贝
C++98
C++11
2.封掉析构函数
3.设计一个类,只能在栈上创建对象
4.设计一个类,不能被继承
1.C++98
2.C++11 final
2.单例模式
1.设计模式
2.单例模式
1.饿汉模式
2.懒汉模式
3.单例对象释放问题
1.特殊类设计
1.设计一个类,不能被拷贝
C++98
将拷贝函数只声明不实现,并且放到私有处。(只不过,在类型内部调用另外的函数进行拷贝就没有办法防止了)
class CopyBan {// ... private:CopyBan(const CopyBan&);CopyBan& operator=(const CopyBan&);//... };C++11
在函数申明后面加入 =delete
class CopyBan {// ...CopyBan(const CopyBan&)=delete;CopyBan& operator=(const CopyBan&)=delete;//... };2.设计一个类,只能在堆上创建对象
1.封掉所有拷贝
C++98
1.先将构造函数封死,这样就无法在栈上创造对象了。但是我们需要提供一个函数调用,使得其在堆上创造对象。
2.创造堆上的函数不能直接修饰,这样会出现逻辑谬论(即想要创造对象,需要调用函数;想要调用函数,需要先创造对象)。所以这里的解决方式是设置静态函数,不需要this指针,所以不需要生成所谓对象才能调用,可以直接调用。
3.特别注意,其实拷贝构造函数也需要被处理一下,因为如果在外部先构造堆上的,随后通过解指针调用给拷贝构造,那么其实也是不算合格的。
class HeapOnly { public:static HeapOnly* CreateObject(){return new HeapOnly;} private:HeapOnly() {}HeapOnly(const HeapOnly&) {} }int main() {HeapOnly* php = HeapOnly::CreateObject(); }C++11
class HeapOnly { public:static HeapOnly* CreateObject(){return new HeapOnly;}HeapOnly(const HeapOnly&) = delete;HeapOnly(const HeapOnly&) = delete; };2.封掉析构函数
1.将析构函数封掉也能达到相同的效果,因为构造了就需要被析构,类型没有检查到可以析构就会报错。
2.此时堆上的类需要被释放掉,也需要重新构造一个destory函数,其类型是类型的指针,不可以是对象本身,因为这样就是手动调用析构函数了。只要调用destory就能释放堆上的空间。
3.设计一个类,只能在栈上创建对象
这样设计使得不能创建在堆和静态上。
class StackOnly { public:static StackOnly CreateObj(){return StackOnly();} private:StackOnly():_a(0){} private:int _a; };这样的设计使得不能在堆上创建但是,能产生静态的对象。
// 禁掉operator new可以把下面用new 调用拷贝构造申请对象给禁掉 void* operator new(size_t size) = delete; void operator delete(void* p) = delete;4.设计一个类,不能被继承
1.C++98
构造函数私有化,子类本来要调用父类的构造函数,没有则不能被继承。
class NonInherit { public:static NonInherit GetInstance(){return NonInherit();} private:NonInherit(){} };2.C++11 final
class A final {// .... };
2.单例模式
1.设计模式
设计模式是一套被反复使用、多数人知晓的、经过分类的、代码设计经验的总结。使用设计模式的目的:为了代码可重用性、让代码更容易被他人理解、保证代码可靠性。 设计模式使代码编写真正工程化;设计模式是软件工程的基石脉络,如同大厦的结构一样。
一些设计理念:迭代器模式,配接器模式,单例模式,工厂模式,观察者模式
2.单例模式
一个类只能创建一个对象,即单例模式,该模式可以保证系统中该类只有一个实例,并提供一个访问它的全局访问点,该实例被所有程序模块共享。
使用样例:内存池的申请1.饿汉模式
特点:
一开始(在main函数之前)就创造对象,就是说不管你将来用不用,程序启动时就创建一个唯一的实例对象
缺点:
1.由于初始化在main函数之前,这样的类数据过多,会使得启动慢;
2.多个单例类有初始化依赖关系,饿汉模式无法控制类的初始化先后关系
class InfoSingleton { public:static InfoSingleton& GetInstance(){return _sins;}void Insert(string name, int money){_info[name] = money;}void Print(){for (auto kv : _info){cout << kv.first << " " << kv.second << endl;}}private:InfoSingleton(){}InfoSingleton(const InfoSingleton& info) = delete;InfoSingleton& operator=(const InfoSingleton& info) = delete;map<string, int> _info;private:static InfoSingleton _sins; };InfoSingleton InfoSingleton::_sins;int main() {InfoSingleton::GetInstance().Insert("张三", 1000);InfoSingleton& info = InfoSingleton::GetInstance();info.Insert("李四", 100);//InfoSingleton copy = InfoSingleton::GetInstance(); //拷贝构造//copy.Insert("***", 10000);return 0; }2.懒汉模式
1.如果单例对象构造十分耗时或者占用很多资源,比如加载插件啊, 初始化网络连接啊,读取文件啊等等,而有可能该对象程序运行时不会用到,那么也要在程序一开始就进行初始化,就会导致程序启动时非常的缓慢。 所以这种情况使用懒汉模式(延迟加载)更好。
2.如果类之间存在依赖关系,也可以使用懒汉模式(延迟加载)。
template<class Lock> class LockGuard { public:LockGuard(Lock& lk):_lk(lk){_lk.lock();}~LockGuard(){_lk.unlock();}private:Lock& _lk; };class _InfoSingleton { public://线程安全问题,多线程一起调用创建对象static _InfoSingleton& GetInstance(){//双检查增加效率if (_psins == nullptr) {LockGuard<mutex> lock(*_smtx);if (_psins == nullptr){_psins = new _InfoSingleton;}}return *_psins;}void Insert(string name, int money){_info[name] = money;}void Print(){for (auto kv : _info){cout << kv.first << " " << kv.second << endl;}}private:_InfoSingleton(){}_InfoSingleton(const _InfoSingleton& info) = delete;_InfoSingleton& operator=(const _InfoSingleton& info) = delete;map<string, int> _info;private:static _InfoSingleton* _psins;static mutex* _smtx; };static _InfoSingleton* _psins = nullptr; static mutex* _smtx;1.这样写是懒汉模式,只创建一次,并且在main函数调用之后创建。
2.该代码有线程安全问题,在C++11后得到解决。
static _InfoSingleton& GetInstance() {static _InfoSingleton sinst;return sinst; }注意:
1.懒汉模式需要注意线程安全问题,所以我们在类中需要有一个唯一的锁,确保判断时是串行访问的。
2.每次都先加锁再进行判断是否为空,其实是非常低效,所以我们需要双判断,第一次判断是为了抛去已经创建过的节省加锁的时间,第二次判断是为了创建对象使用的,而锁夹在中间确保第二次的判断是串行的。
3.饿汉模式不需要注意线程安全问题,因为饿汉在main调用之前就已经存在了,没有所谓的线程可以创建其他的对象。
3.单例对象释放问题
1.一般而言单例类不需要释放内存,因为单例出现的环境就是全局的,它的目的就是陪到进程执行到最后,那么其实不释放,进程结束后,操作系统也会将这一部分的资源回收。
2.特别的,如果我们需要在最后单例有一定要求,我们可以手写出析构,比如进程结束需要保存一些数据到文件中,那么我们析构可以手写要求。
相关文章:
C++语法(26)--- 特殊类设计
C语法(25)--- 异常与智能指针_哈里沃克的博客-CSDN博客https://blog.csdn.net/m0_63488627/article/details/131537799?spm1001.2014.3001.5501 目录 1.特殊类设计 1.设计一个类,不能被拷贝 C98 C11 2.设计一个类,只能在堆上…...
YAML+PyYAML笔记 2 | YAML缩进、分离、注释简单使用
2 | YAML缩进、分离、注释简单使用 1 简介2 缩进3 分离4 多行文本4.1 折叠块4.2 字面块4.3 引用块 5 注释5.1 行内注释5.2 块注释5.3 完美注释示例 1 简介 YAML 不是一种标记语言,而是一种数据格式;使用缩进和分离来表示数据结构,不需要使用…...
Array(20) 和 Array.apply(null, {length: 20})
1.Array(20) 其结果是: 创建了一个长度为20,但元素均为 empty 的数组。 2.Array.apply(null, { length: 20 }) 其结果是: 创建了一个长度为20,但元素均为 undefined 的数组。 3.异同 3.1相同 console.log(arr1[0] arr2[0]) /…...
Mind+积木编程控制小水泵给宠物喂水
前期用scratch,带着小朋友做了大鱼吃小鱼、桌面弹球、小学生计算器3个作品,小朋友收获不小。关键是小家伙感兴趣,做出来后给家人炫耀了一圈后,兴趣大增,嚷嚷着要做更好玩的。 最近,娃妈从抖音上买了个小猫喝…...
【Linux从入门到精通】进程的控制(进程替换)
本篇文章会对进程替换进行讲解。希望本篇文章会对你有所帮助 文章目录 一、进程替换概念 二、进程替换函数 2、1 execl 2、2 execlp 2、3 execv 2、3 execle 2、4 execve 三、总结 🙋♂️ 作者:Ggggggtm 🙋♂️ 👀 专栏&…...
rancher平台上强制删除pod服务操作
背景: 在日常paas平台运维工作中需要对rancher平台进行巡检的工作,在巡检时发现在rancher管理界面无法删除异常的pod服务, 处理: 像这样的情况就是k8s集群的pod无法通过默认的方式去删除掉pod服务,这时候只能是手工强制…...
【Docker】Docker的通信安全
Docker的通信安全 前言一、Docker 容器与虚拟机的区别1. 隔离与共享2. 性能与损耗 二、Docker 存在的安全问题1. Docker 自身漏洞2. Docker 源码问题 三、Docker 架构缺陷与安全机制1. 容器之间的局域网攻击2. DDoS 攻击耗尽资源3. 有漏洞的系统调用4. 共享 root 用户权限 四、…...
c# 函数中可选参数太多,想设置最后一个参数,又不想修改前面默认参数
C#中,你可以使用命名参数来指定你想要设置的可选参数,而保留其他参数的默认值不变。通过使用命名参数,你可以根据需要选择要为哪些参数提供值,而无需按照它们在函数签名中的顺序提供参数值。 以下是一个示例,演示如何…...
openvino资料(1)
1、c++ - OpenVino model outputs zeroes - Stack Overflow 2、https://chinait-intel.oss-cn-beijing.aliyuncs.com/OpenVINO/Ubuntu20.04%E7%8E%AF%E5%A2%83%E4%B8%8B%E4%BD%BF%E7%94%A8OpenVINO%E9%83%A8%E7%BD%B2BiSeNetV2%E6%A8%A1%E5%9E%8B.pdf 3、c++ - How to cre...
第71篇:某银行外网打点到内网核心区红队评估复盘
Part1 前言 大家好,我是ABC_123。本期分享一篇ABC_123曾经做的针对一家银行的红队评估项目,持续时间两周,难度非常大,但是最终打到了银行核心业务区,今天就复盘一下全过程,希望红蓝双方都能得到一些启示&a…...
网络安全 Day21-数据库知识
数据库知识 1. 什么是数据库2. 为什么需要数据库(分类不清晰)3. 数据库的种类3.1 关系型数据库3.2 NOSQL 数据库3.3 new sql (国产数据库)分布式数据库3.4 云数据库 4. mysql 关系型数据库5. 安装mariadb6. 为mariadb设置密码7. M…...
python测试开发面试常考题:装饰器
目录 简介 应用 第一类对象 装饰器 描述器descriptor 资料获取方法 简介 Python 装饰器是一个可调用的(函数、方法或类),它获得一个函数对象 func_in 作为输入,并返回另一函数对象 func_out。它用于扩展函数、方法或类的行为。 装饰器模式通常用…...
语音同声翻译软件让你不再为语言障碍困扰
从前有一个叫黄俊的小伙子,他有一个大梦想:环游世界!但是,他只会说中文,而去到外国又怎么跟当地人交流呢?为了实现自己的梦想,黄俊开始了寻找能帮他解决问题的捷径。这时,方娜向他介…...
又有一个手艺人震惊了B站用户
飞瓜数据(B站版)【热门视频榜】周榜显示,霸占全站视频流量第一的是来自UP主爱捣鼓的邢志磊发布的作品《我花了半年时间给猫做了个房子》。 视频在一周时间内新增播放1232.2万,新增点赞139.4万。 根据视频详细数据显示,…...
HDFS的设计目标和重要特性
HDFS的设计目标和重要特性 设计目标HDFS重要特性主从架构分块存储机制副本机制namespace元数据管理数据块存储 设计目标 硬件故障(Hardware Failure)是常态,HDFS可能有成百上千的服务器组成,每一个组件都有可能出现故障。因此古见检测和自动快速恢复的H…...
【JMeter】JMeter添加插件
目录 一、前言 二、插件管理器 三、推荐插件 1.Custom Thread Groups (1)Ultmate Thread Group (2)Stepping Thread Group 2.3 Basic Graph 资料获取方法 一、前言 在我们的工作中,我们可以利用一些插件来帮…...
测牛学堂:车载测试面试总结之语音助手相关
车载语音助手的工作原理? 语音助手的工作原理总结下来可以分为4个步骤: 1 通过麦克风采集驾驶员的语音指令 2将语音信号转换为数字信号 3过语音识别技术将语音指令转换为计算机可以理解的指令 4 通过语音合成技术将计算机的回应转换为语音输出 车载…...
Android开发之Fragment动态添加与管理
文章目录 主界面布局资源两个工具Fragment主程序 主界面布局资源 在activity_main.xml中,声明两个按钮备用,再加入一个帧布局,待会儿用来展示Fragment。 <?xml version"1.0" encoding"utf-8"?> <LinearLayo…...
Python爬虫+数据可视化:分析唯品会商品数据
目录 前言数据来源分析1. 明确需求2. 抓包分析:通过浏览器自带工具: 开发者工具 代码实现步骤: 发送请求 -> 获取数据 -> 解析数据 -> 保存数据发送请求解析数据保存数据 数据可视化先读取数据泳衣商品性别占比商品品牌分布占比各大品牌商品售价平均价格各…...
el-tree数据渲染超出省略
el-tree数据渲染超出省略 问题 <el-tree:data"deptOptions":props"defaultProps":expand-on-click-node"false":filter-node-method"filterNode"ref"tree"default-expand-allhighlight-currentnode-click"handleNo…...
VB.net复制Ntag213卡写入UID
本示例使用的发卡器:https://item.taobao.com/item.htm?ftt&id615391857885 一、读取旧Ntag卡的UID和数据 Private Sub Button15_Click(sender As Object, e As EventArgs) Handles Button15.Click轻松读卡技术支持:网站:Dim i, j As IntegerDim cardidhex, …...
376. Wiggle Subsequence
376. Wiggle Subsequence 代码 class Solution { public:int wiggleMaxLength(vector<int>& nums) {int n nums.size();int res 1;int prediff 0;int curdiff 0;for(int i 0;i < n-1;i){curdiff nums[i1] - nums[i];if( (prediff > 0 && curdif…...
Vue2 第一节_Vue2上手_插值表达式{{}}_访问数据和修改数据_Vue开发者工具
文章目录 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染2. 插值表达式{{}}3. 访问数据和修改数据4. vue响应式5. Vue开发者工具--方便调试 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染 准备容器引包创建Vue实例 new Vue()指定配置项 ->渲染数据 准备一个容器,例如: …...
LLM基础1_语言模型如何处理文本
基于GitHub项目:https://github.com/datawhalechina/llms-from-scratch-cn 工具介绍 tiktoken:OpenAI开发的专业"分词器" torch:Facebook开发的强力计算引擎,相当于超级计算器 理解词嵌入:给词语画"…...
学习STC51单片机32(芯片为STC89C52RCRC)OLED显示屏2
每日一言 今天的每一份坚持,都是在为未来积攒底气。 案例:OLED显示一个A 这边观察到一个点,怎么雪花了就是都是乱七八糟的占满了屏幕。。 解释 : 如果代码里信号切换太快(比如 SDA 刚变,SCL 立刻变&#…...
微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据
微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据 Power Query 具有大量专门帮助您清理和准备数据以供分析的功能。 您将了解如何简化复杂模型、更改数据类型、重命名对象和透视数据。 您还将了解如何分析列,以便知晓哪些列包含有价值的数据,…...
Mysql中select查询语句的执行过程
目录 1、介绍 1.1、组件介绍 1.2、Sql执行顺序 2、执行流程 2.1. 连接与认证 2.2. 查询缓存 2.3. 语法解析(Parser) 2.4、执行sql 1. 预处理(Preprocessor) 2. 查询优化器(Optimizer) 3. 执行器…...
JVM 内存结构 详解
内存结构 运行时数据区: Java虚拟机在运行Java程序过程中管理的内存区域。 程序计数器: 线程私有,程序控制流的指示器,分支、循环、跳转、异常处理、线程恢复等基础功能都依赖这个计数器完成。 每个线程都有一个程序计数…...
C++课设:简易日历程序(支持传统节假日 + 二十四节气 + 个人纪念日管理)
名人说:路漫漫其修远兮,吾将上下而求索。—— 屈原《离骚》 创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 专栏介绍:《编程项目实战》 目录 一、为什么要开发一个日历程序?1. 深入理解时间算法2. 练习面向对象设计3. 学习数据结构应用二、核心算法深度解析…...
代码规范和架构【立芯理论一】(2025.06.08)
1、代码规范的目标 代码简洁精炼、美观,可持续性好高效率高复用,可移植性好高内聚,低耦合没有冗余规范性,代码有规可循,可以看出自己当时的思考过程特殊排版,特殊语法,特殊指令,必须…...
