C++单例模式的实现
单例模式就是在整个程序运行期都只有一个实例。在代码实现方面,我们要限制new出多于一个对象这种情况的发生。而不是仅仅依靠无保障的约定。
目前大多数的编程语言的做法都是私有化构造函数,对外提供一个获取实例的接口。这样做的目的使实例的创建不能在类外部完成,这样我们只需要在内部保障实例只创建一次即可。我们用一个例子来说明C++的单例:
#include <iostream>
using namespace std;class TestCls{private:TestCls(){} // 构造函数私有化,在外部就无法通过new运算符创建新实例// 声明单例里的指针,static的成员在这里只是声明,它的初始化还没有完成static TestCls *m_instance;public:~TestCls(){//析构函数cout << "TestCls is destroying" << endl;}// 对外暴露一个接口获得单例static TestCls* getinstance(){if(m_instance == NULL){// new出来的对象,一定要用delete运算符删除对应的指针m_instance = new TestCls();// 巧妙的地方static MyGC mygc;}return m_instance;}void test(){cout << "test" << endl;}// 在单例里再定义一个内部类class MyGC {public:~MyGC(){//在内部类的析构函数里delete掉单例if(TestCls::m_instance){delete TestCls::m_instance;TestCls::m_instance = NULL;}}};
};// static 成员的初始化
TestCls * TestCls::m_instance = NULL;int main(){//获取单例TestCls * ptr = TestCls::getinstance();cout << ptr << endl;ptr = TestCls::getinstance();cout << ptr <<endl;return 0;
}
定义单例基本上来说是很简单的,就是先私有化构造函数,单例内部new出这个实例,并对外提供获取实例的接口。在这里我想特别分享一下,为什么要弄一个内部类的作用。
目的只有一个就是当程序退出时主动delete掉实例。其次new出来的指针要主动delete掉,malloc出来的东西要主动free掉,这些是编程的好习惯。
我在new出单例时,初始化一个内部类static MyGC mygc; 带上static关键字后,它的生命周期会一直持续到程序退出,因为这个对象不是new也不是malloc出来的,所有它就不会在堆内存里,它会在静态代码区,而单例是new出来的它就在堆内存里。在程序退出时,就会调用内部类的析构函数,这样我们就可以借此delete掉单例。这是一个很巧妙的使用。
C++单例的增强
前面的代码中我们可以看到每个线程调用getinstance()都会先判断是否空,是的话就new一个新的实例。实际上,我们可以改进一下这段代码,C++11提供了call_once的功能,就是说这个功能可以让某个函数只被调用一次。那么我们可以将创建单例的代码,抽象成一个方法,并使用这个方法只被调用一次,这能给我们带来什么好处呢?
我们上面的代码可能没有解决好在多线程中,这个单例的初始化需要互斥的问题。也就是说可能存在多个线程在同时初始化这个实例。一般的做法就是给初始化的代码块加锁,即:
m_mutex.lock();
if(m_instance == NULL){m_instance = new TestCls();static MyGC mygc;
}
m_mutex.unlock();
现在用c++11提供的call_once函数功能就可以轻松解决这个初始化需要互斥的问题。调整过的部分:
once_flag gflag;
class TestCls{private:...static void createinstance(){if(m_instance == NULL) {m_instance = new TestCls();static MyGC mygc;}}public:...static TestCls* getinstance(){call_once(gflag,createinstance);return m_instance;}......
};
我们还可以再提高一些效率:
once_flag gflag;
class TestCls{private:...static void createinstance(){if(m_instance == NULL) {m_instance = new TestCls();static MyGC mygc;}}public:...static TestCls* getinstance(){if(m_instance == NULL) { // 进一步提高效率call_once(gflag,createinstance);}return m_instance;}......
};
相关文章:
C++单例模式的实现
单例模式就是在整个程序运行期都只有一个实例。在代码实现方面,我们要限制new出多于一个对象这种情况的发生。而不是仅仅依靠无保障的约定。 目前大多数的编程语言的做法都是私有化构造函数,对外提供一个获取实例的接口。这样做的目的使实例的创建不能在…...
rust函数 stuct struct方法 关联函数
本文结合2个代码实例主要介绍了rust函数定义方法,struct结构体定义、struct方法及关联函数等相关基础知识。 代码1: main.rc #[derive(Debug)]//定义一个结构体 struct Ellipse {max_semi_axis: u32,min_semi_axis: u32, }fn main() {//椭圆࿰…...
浅谈基于中台模式的大数据生态体系的理解
这篇文章主要浅谈一下我对大数据生态体系建设的理解。 大数据生态系统为高并发,高吞吐,高峰值,高堆积等大规模数据的采集,处理,计算,存储,服务提供了完善的处理体系,致力于打造核心数…...
MySQL的锁机制
一:概述 锁是计算机协调多个进程或线程并发访问某一资源的机制(避免争抢); 在数据库中,除传统的计算资源(如CPU,RAM,I/O等)的争用以外,数据也是一种供许多用…...
已解决ImportError: cannot import name ‘PILLOW_VERSION‘异常的正确解决方法,亲测有效!!!
已解决ImportError: cannot import name PILLOW_VERSION异常的正确解决方法,亲测有效!!! 文章目录 问题分析 报错原因 解决思路 解决方法 总结 在Python项目开发中,依赖管理是保证项目正常运行的关键环节。然而&…...
力扣:300. 最长递增子序列
动态规划: 1. 先定义dp数组来表示在下标为i时最长递增子序列,先初始化一下每个下标的值为dp【i】1。同时我们要判断在下标i之前的最长的递增子序列为多少,在判断当前的下标i是否满足递增的条件满足的话就进行dp【i】的重新赋值。之后要更新接受的最长递…...
Swing程序设计(10)列表框,文本框,文本域,密码框
文章目录 前言一、列表框二、文本框(域) 1.文本框2.文本域三、密码框总结 前言 该篇文章简单介绍了Java中Swing组件里的列表框、文本框、密码框。 一、列表框 列表框(JList)相比下拉框,自身只是在窗体上占据固定的大小…...
【Java八股面试系列】JVM-常见参数设置
目录 堆内存相关 显式指定堆内存–Xms和-Xmx 显式新生代内存(Young Generation) 显式指定永久代/元空间的大小 垃圾收集相关 垃圾回收器 GC 日志记录 处理 OOM JDK监控和故障处理工具总结 堆内存相关 Java 虚拟机所管理的内存中最大的一块,Java 堆是所有线…...
【Python--Web应用框架大比较】
🚀 作者 :“码上有前” 🚀 文章简介 :Python 🚀 欢迎小伙伴们 点赞👍、收藏⭐、留言💬 Django Django太重了,除了web框架,自带ORM和模板引擎,灵活和自由度不…...
Effective Objective-C 学习第三周
理解引用计数 Objective-C 使用引用计数来管理内存:每个对象都有个可以递增或递减的计数器。如果想使某个对象继续存活,那就递增其引用计数:用完了之后,就递减其计数。计数变为 0时,就可以把它销毁。 在ARC中…...
人工智能学习与实训笔记(四):神经网络之NLP基础—词向量
人工智能专栏文章汇总:人工智能学习专栏文章汇总-CSDN博客 本篇目录 四、自然语言处理 4.1 词向量 (Word Embedding) 4.1.1 词向量的生成过程 4.1.2 word2vec介绍 4.1.3 word2vec:skip-gram算法的实现 4.2 句向量 - 情感分析 4.2.1 LSTM (Long S…...
【教程】Kotlin语言学习笔记(一)——认识Kotlin(持续更新)
写在前面: 如果文章对你有帮助,记得点赞关注加收藏一波,利于以后需要的时候复习,多谢支持! 【Kotlin语言学习】系列文章 第一章 《认识Kotlin》 文章目录 【Kotlin语言学习】系列文章一、Kotlin介绍二、学习路径 一、…...
MySQL性能分析1
1、查看执行频次 查看当前数据库的INSERT,UPDATE,DELETE,SELECT的访问频次,得到当前数据库是以插入,更新和删除为主还是以查询为主,如果是以插入,更新和删除为主的话,那么优化比重可以轻一点儿。 语法: …...
四、案例 - Oracle数据迁移至MySQL
Oracle数据迁移至MySQL 一、生成测试数据表和数据1.在Oracle创建数据表和数据2.在MySQL创建数据表 二、生成模板文件1.模板文件内容2.模板文件参数详解2.1 全局设置2.2 数据读取(Reader)2.3 数据写入(Writer)2.4 性能设置 三、案例…...
ABC340 A-F题解
文章目录 A题目AC Code: B题目AC Code: C题目AC Code: D题目AC Code: E题目思路做法时间复杂度AC Code: F题目思路AC Code: A 题目 模拟即可,会循环都能写。 AC Code: #include …...
微软 CMU - Tag-LLM:将通用大语言模型改用于专业领域
文章目录 一、前言二、主要内容三、总结 🍉 CSDN 叶庭云:https://yetingyun.blog.csdn.net/ 一、前言 论文地址:https://arxiv.org/abs/2402.05140 Github 地址:https://github.com/sjunhongshen/Tag-LLM 大语言模型(…...
Kafka集群安装与部署
集群规划 准备工作 安装 安装包下载:链接:https://pan.baidu.com/s/1BtSiaf1ptLKdJiA36CyxJg?pwd6666 Kafka安装与配置 1、上传并解压安装包 tar -zxvf kafka_2.12-3.3.1.tgz -C /opt/moudle/2、修改解压后的文件名称 mv kafka_2.12-3.3.1/ kafka…...
C++初阶(十一) list
一、list的介绍及使用 1.1 list的介绍 list的文档介绍 1. list是可以在常数范围内在任意位置进行插入和删除的序列式容器,并且该容器可以前后双向迭代。 2. list的底层是双向链表结构,双向链表中每个元素存储在互不相关的独立节点中,在节点…...
图像卷积、步长、填充、特征图、多通道卷积、权重共享、感受野、池化
图像卷积、步长、填充、特征图、多通道卷积、权重共享、感受野、池化 卷积神经网络的一些基本概念:图像卷积、步长、填充、特征图、多通道卷积、权重共享、感受野、池化 1.图像卷积、步长、填充 图像卷积:卷积核矩阵在一个原始图像矩阵上 “从上往下、…...
CMake进行C/C++与汇编混合编程
1. 前提 这篇文章记录一下怎么用CMake进行项目管理, 并用C/C和汇编进行混合编程, 为了使用这项技术, 必须在VS的环境中安装好cmake组件 由于大部分人不会使用C/C与汇编进行混合编程的情况。所以这篇文章并不适用于绝大部分人不会对其中具体细节进行过多叙述。只是做一些简单的…...
XML Group端口详解
在XML数据映射过程中,经常需要对数据进行分组聚合操作。例如,当处理包含多个物料明细的XML文件时,可能需要将相同物料号的明细归为一组,或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码,增加了开…...
RocketMQ延迟消息机制
两种延迟消息 RocketMQ中提供了两种延迟消息机制 指定固定的延迟级别 通过在Message中设定一个MessageDelayLevel参数,对应18个预设的延迟级别指定时间点的延迟级别 通过在Message中设定一个DeliverTimeMS指定一个Long类型表示的具体时间点。到了时间点后…...
python打卡day49
知识点回顾: 通道注意力模块复习空间注意力模块CBAM的定义 作业:尝试对今天的模型检查参数数目,并用tensorboard查看训练过程 import torch import torch.nn as nn# 定义通道注意力 class ChannelAttention(nn.Module):def __init__(self,…...
解决Ubuntu22.04 VMware失败的问题 ubuntu入门之二十八
现象1 打开VMware失败 Ubuntu升级之后打开VMware上报需要安装vmmon和vmnet,点击确认后如下提示 最终上报fail 解决方法 内核升级导致,需要在新内核下重新下载编译安装 查看版本 $ vmware -v VMware Workstation 17.5.1 build-23298084$ lsb_release…...
解锁数据库简洁之道:FastAPI与SQLModel实战指南
在构建现代Web应用程序时,与数据库的交互无疑是核心环节。虽然传统的数据库操作方式(如直接编写SQL语句与psycopg2交互)赋予了我们精细的控制权,但在面对日益复杂的业务逻辑和快速迭代的需求时,这种方式的开发效率和可…...
转转集团旗下首家二手多品类循环仓店“超级转转”开业
6月9日,国内领先的循环经济企业转转集团旗下首家二手多品类循环仓店“超级转转”正式开业。 转转集团创始人兼CEO黄炜、转转循环时尚发起人朱珠、转转集团COO兼红布林CEO胡伟琨、王府井集团副总裁祝捷等出席了开业剪彩仪式。 据「TMT星球」了解,“超级…...
微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据
微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据 Power Query 具有大量专门帮助您清理和准备数据以供分析的功能。 您将了解如何简化复杂模型、更改数据类型、重命名对象和透视数据。 您还将了解如何分析列,以便知晓哪些列包含有价值的数据,…...
解决:Android studio 编译后报错\app\src\main\cpp\CMakeLists.txt‘ to exist
现象: android studio报错: [CXX1409] D:\GitLab\xxxxx\app.cxx\Debug\3f3w4y1i\arm64-v8a\android_gradle_build.json : expected buildFiles file ‘D:\GitLab\xxxxx\app\src\main\cpp\CMakeLists.txt’ to exist 解决: 不要动CMakeLists.…...
Vue 模板语句的数据来源
🧩 Vue 模板语句的数据来源:全方位解析 Vue 模板(<template> 部分)中的表达式、指令绑定(如 v-bind, v-on)和插值({{ }})都在一个特定的作用域内求值。这个作用域由当前 组件…...
云安全与网络安全:核心区别与协同作用解析
在数字化转型的浪潮中,云安全与网络安全作为信息安全的两大支柱,常被混淆但本质不同。本文将从概念、责任分工、技术手段、威胁类型等维度深入解析两者的差异,并探讨它们的协同作用。 一、核心区别 定义与范围 网络安全:聚焦于保…...
