C++单例设计模式

C++单例设计模式

文章目录

  • C++单例设计模式
    • 单例设计模式介绍
      • 饿汉式单例设计模式
      • 懒汉式单例设计模式
      • 什么是可重入函数

单例设计模式介绍

单例模式指的是,无论怎么获取,永远只能得到该类类型的唯一一个实例对象,那么设计一个单例就必须要满足下面三个条件:

  1. 构造函数私有化,这样用户就不能任意定义该类型的对象了
  2. 定义该类型唯一的对象
  3. 通过一个static静态成员方法返回唯一的对象实例

在写单例设计模式的时候,我们就可以采用这样的步骤来写单例模式

饿汉式单例设计模式

#include <iostream>

//饿汉式单例设计模式
class Single
{
public:
	//3. 获取类的唯一实例对象的接口方法
	static Single* getInstacne() { return &instance; }
	void printSingle()
	{
		std::cout << "hello codechen" << char(10);
	}
private:
	//2. 定义一个唯一的类的实例化的对象
	static Single instance;

	//1. 构造函数的私有化,不能够自己主动的去调用构造函数
	Single()
	{//在实际的项目中,构造函数可能会需要做很多的工作
	//比如说对一些成员变量的初始化,对一些数据的读取等等

	}

	Single(const Single&) = delete;
	Single& operator = (const Single&) = delete;
};
Single Single::instance{};

int main()
{
	Single* ptr1 = Single::getInstacne();
	ptr1->printSingle();
	delete ptr1;
	return 0;
}

懒汉式单例设计模式

#include <iostream>

//懒汉式单例设计模式
class Single
{
public:
	//3. 获取类的唯一实例对象的接口方法
	static Single* getInstacne() 
	{ 
		std::cout << "hello codechen,你成功的调用了一次构造函数" << char(10);
		if (instance == nullptr)
		{
			std::cout << "在这里对instance进行了初始化" << char(10);
			instance = new Single();
		}
		return instance;
	}
private:
	//2. 定义一个唯一的类的实例化的对象,为指针
	static Single* instance;

	//1. 构造函数的私有化,不能够自己主动的去调用构造函数
	Single()
	{//在实际的项目中,构造函数可能会需要做很多的工作
	//比如说对一些成员变量的初始化,对一些数据的读取等等

	}

	Single(const Single&) = delete;
	Single& operator = (const Single&) = delete;
};
Single* Single::instance = nullptr;

int main()
{
	Single* ptr1 = Single::getInstacne();
	Single* ptr2 = Single::getInstacne();
	Single* ptr3 = Single::getInstacne();
    
    delete ptr1;
    delete ptr2;
    delete ptr3;
    
	return 0;
}

什么是可重入函数

下面讲到线程安全问题,先引入一个可重入函数的概念

可重入函数是指在程序中可以被多个任务安全地调用的函数。这类函数在执行过程中不会修改全局变量,而是使用局部变量和线程特定数据等机制来保存数据。可重入函数在收到信号后不会导致数据出错,因此可以在信号处理函数中使用。与之相反,不可重入函数在收到信号后可能会修改全局变量,从而导致程序出现不可预料的后果。

在Linux系统编程中,为了提高程序的稳定性,应尽量使用可重入函数进行信号处理。同时,避免在信号处理函数中使用不可重入函数,以降低信号处理函数的复杂性。

可重入函数的特点:

  1. 使用局部变量而非全局变量。
  2. 避免使用静态数据结构。
  3. 不调用malloc()或free()等内存分配函数。
  4. 使用线程特定数据(如pthread_key_t)保存数据,以实现多线程间的数据隔离。

总之,可重入函数是在多任务、多线程环境下保证程序稳定性的重要手段。

为什么懒汉模式可能会涉及到线程安全的问题

	static Single* getInstacne() 
	{ 
		std::cout << "hello codechen,你成功的调用了一次构造函数" << char(10);
		if (instance == nullptr)
		{
			//在这里我们进行多种的操作,比如说开闭内存,构造对象和给Single赋值等
			std::cout << "在这里对instance进行了初始化" << char(10);
			instance = new Single();
		}
		return instance;
	}

我们看到这个函数,在if的判断语句中,在这里我们进行多种的操作,比如说开闭内存,构造对象和给Single赋值等。

如果一个线程,比如线程A进来了,看到这个instance == nullptr,会对她进行操作,这个时候如果线程B也进来了,这个线程A还没有对instance 赋值的话,这个线程B也是认为这个instance是没有赋值的,所以她也是会进入到去执行if内的语句。

如何解决这个问题

在这里我们最好的解决方式就是锁加上双重判断的方式

我们为什么要双重判断?

比如我线程A进来了,A拿到了锁,但是这个时候没有对instance赋值,线程B也是可以进来的,但是拿不到锁会阻塞在那个地方,如果线程A结束了,线程B还是会去执行if里面的语句,所以这里还要再加上一个if的双重判断。

#include <iostream>
#include <mutex>
#include <thread>
using namespace std;
std::mutex mylock;
//线程安全的,懒汉式单例设计模式
class Single
{
public:
	//3. 获取类的唯一实例对象的接口方法
	//锁加上双重判断
	static Single* getInstacne() 
	{ 
		std::cout << "hello codechen,你成功的调用了一次构造函数" << char(10);
		if (instance == nullptr)
		{
			lock_guard<std::mutex> guard(mylock);
			if (instance == nullptr)
			{
				//在这里我们进行多种的操作,比如说开闭内存,构造对象和给Single赋值等
				std::cout << "在这里对instance进行了初始化" << char(10);
				instance = new Single();
			}
		}
		return instance;
	}
private:
	//2. 定义一个唯一的类的实例化的对象,为指针
	static Single* volatile instance;

	//1. 构造函数的私有化,不能够自己主动的去调用构造函数
	Single()
	{//在实际的项目中,构造函数可能会需要做很多的工作
	//比如说对一些成员变量的初始化,对一些数据的读取等等

	}

	Single(const Single&) = delete;
	Single& operator = (const Single&) = delete;
};
Single* Single::instance = nullptr;

int main()
{
	Single* ptr1 = Single::getInstacne();
	Single* ptr2 = Single::getInstacne();
	Single* ptr3 = Single::getInstacne();
    
    delete ptr1;
    delete ptr2;
    delete ptr3;
	return 0;
}

关于volatile的作用

在这里插入图片描述

附加问题:

#include <iostream>
using namespace std;

class CSingleton
{
public:
	static CSingleton* getInstance()
	{
		static CSingleton single; // 懒汉式单例模式,定义唯一的对象实例
		return &single;
	}
private:
	static CSingleton *single;
	CSingleton() { cout << "CSingleton()" << endl; }
	~CSingleton() { cout << "~CSingleton()" << endl;}
	CSingleton(const CSingleton&);
};
int main()
{
	CSingleton *p1 = CSingleton::getInstance();
	CSingleton *p2 = CSingleton::getInstance();
	CSingleton *p3 = CSingleton::getInstance();
    
    delete ptr1;
    delete ptr2;
    delete ptr3;
	return 0;
}

在这里插入图片描述

对于static静态局部变量的初始化,编译器会自动对它的初始化进行加锁和解锁控制,使静态局部变量的初始化成为线程安全的操作,不用担心多个线程都会初始化静态局部变量,因此上面的懒汉单例模式是线程安全的单例模式!

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

横屏转竖屏:一键轻松转换,让视频更适应屏幕!

想象一下&#xff0c;你有一批横屏视频&#xff0c;想要将它们快速变为适应手机竖屏观看的格式&#xff0c;但又不想一个个手动处理。现在&#xff0c;有了我们的创意批量剪辑神器&#xff0c;这些烦恼全部消失&#xff01;只需简单几步&#xff0c;就能将横屏视频批量变身成为…

VScode的入门手册(IDEA迁移到VScode)

从IDEA迁移到VScode的过程中&#xff0c;会有很多不适应的地方&#xff0c;下面算是一篇VScode的入门手册&#xff0c;也可以说是从IDEA迁移到VScode的手册。 命令面板&#xff08;Command Palette&#xff09; 允许你快速访问和执行命令。 在 Visual Studio Code 中&#x…

3分钟了解Android中稳定性测试

一、什么是Monkey Monkey在英文里的含义是猴子&#xff0c;在测试行业的学名叫“猴子测试”&#xff0c;指的是没有测试经验的人甚至是根本不懂计算机的人&#xff08;就像一只猴子&#xff09;&#xff0c;不需要知道程序的任何用户交互方面的知识&#xff0c;给他一个程序&a…

0开始配置Cartographer建图和导航定位

0开始配置Cartographer 日期&#xff1a;12-19 硬件&#xff1a;激光雷达IMU 小车的tf变换&#xff1a; 建图配置 lua文件配置&#xff1a;my_robot.lua include "map_builder.lua" include "trajectory_builder.lua"options {map_builder MAP_BUILDE…

【音视频 ffmpeg 学习】 RTMP推流 mp4文件

1.RTMP(实时消息传输协议)是Adobe 公司开发的一个基于TCP的应用层协议。 2.RTMP协议中基本的数据单元称为消息&#xff08;Message&#xff09;。 3.当RTMP协议在互联网中传输数据的时候&#xff0c;消息会被拆分成更小的单元&#xff0c;称为消息块&#xff08;Chunk&#xff…

基于Freeswitch实现的Volte网视频通知应用

现在运营商的Volte网络已经很好的支持视频通话了&#xff0c;因此在原来的电话语音通知的基础上&#xff0c;可以更进一步实现视频的通知&#xff0c;让用户有更好的体验&#xff0c;本文就从技术角度&#xff0c;基于Freeswitch来实现此类应用&#xff08;本文假设读者已对Fre…

C语言编写Windows程序:组合启用/禁用Telnet客户端,并Telnet指定ip和端口

本文程序是将启用/禁用Telnet客户端的命令进行组合&#xff0c;单个命令的解析可参考文章&#xff1a; 启用/禁用Windows功能中的Telnet客户端的命令_()命令将阻止使用telnintel-CSDN博客 源代码如下&#xff1a; #include <stdio.h> #include <stdlib.h> #include…

【Java EE初阶五】wait及notify关键字

1. wait和notify的概念 所谓的wait和notify其实就是等待、通知机制&#xff1b;该机制的作用域join类似&#xff1b;由于多个线程之间是随机调度的&#xff0c;引入wait和notify就是为了能够从应用层面上&#xff0c;干预到多个不同线程代码的执行顺序&#xff0c;此处的干预&a…

小米电脑管家 - 手机平板电脑家居互联

系列文章目录 前言 联想电脑安装小米电脑管家实现设备互联 如图&#xff0c;将 小米平板 5 Pro 作为联想笔记本 GeekPro 5000 &#xff08;这垃圾电脑&#xff09;的副屏。 可以在小米平板控制笔记本&#xff0c;如图所示 一、官方使用手册 参考&#xff1a;小米电脑管家帮助 …

大语言模型发展史

前言 2023年可谓是生成式AI元年&#xff0c;大语言模型从崭露头角到锋芒毕露&#xff0c;已然成为人工智能领域的关键推动力。这一创新性的技术不仅在自然语言处理领域崭露头角&#xff0c;更深刻地改变了我们对人机交互、智能助手和信息处理的认知。那么大语言模型的发展历程…

thinkphp+vue+mysql企业车辆管理系统m117l

“企业车辆管理系统”是运用php语言和vue框架&#xff0c;以Mysql数据库为基础而发出来的。为保证我国经济的持续性发展&#xff0c;必须要让互联网信息时代在我国日益壮大&#xff0c;蓬勃发展。伴随着信息社会的飞速发展&#xff0c;企业车辆管理系统所面临的问题也一个接一个…

基于策略模式和简单工厂模式实现zip、tar、rar、7z四种压缩文件格式的解压

推荐语 这篇技术文章深入探讨了基于策略模式和简单工厂模式实现四种常见压缩文件格式的解压方法。通过阅读该文章&#xff0c;你将了解到如何利用这两种设计模式来实现灵活、可扩展的解压功能&#xff0c;同时适应不同的压缩文件格式。如果你对设计模式和文件处理感兴趣或刚好…

github鉴权失败

问题&#xff1a; 如上图所示 git push 时发生了报错&#xff0c;鉴权失败&#xff1b; 解决方案 Settings->Developer settings->Personal access tokens->Generate new token。创建新的访问密钥&#xff0c;勾选repo栏&#xff0c;选择有效期&#xff0c;为密钥命…

Android MVVM 写法

前言 Model&#xff1a;负责数据逻辑 View&#xff1a;负责视图逻辑 ViewModel&#xff1a;负责业务逻辑 持有关系&#xff1a; 1、ViewModel 持有 View 2、ViewModel 持有 Model 3、Model 持有 ViewModel 辅助工具&#xff1a;DataBinding 执行流程&#xff1a;View &g…

OpenStack云计算(-) 简介与部署Keystone

一.OpenStack简介 什么是云计算:云计算是一种按使用量付费的模式,这种模式提供可用的、便捷的、按需的网络访问,进入可配置的计算资源共享池(资源包括网络,服务器,存储,应用软件,服务) 云计算所包含的几个层次服务&#xff1a; SaaS ( Software as a Service ) :把在线软件作…

【开源】基于Vue+SpringBoot的公司货物订单管理系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 客户管理模块2.2 商品维护模块2.3 供应商管理模块2.4 订单管理模块 三、系统展示四、核心代码4.1 查询供应商信息4.2 新增商品信息4.3 查询客户信息4.4 新增订单信息4.5 添加跟进子订单 五、免责说明 一、摘要 1.1 项目…

Prometheus通过consul实现自动服务发现

环境,软件准备 本次演示环境&#xff0c;我是在虚拟机上安装 Linux 系统来执行操作&#xff0c;以下是安装的软件及版本&#xff1a; System: CentOS Linux release 7.6Docker: 24.0.5Prometheus: v2.37.6Consul: 1.6.1 注意&#xff1a;这里为了方便启动 Prometheus、Consul服…

Elasticsearch:使用 ELSER v2 文本扩展进行语义搜索

Elastic 提供了一个强大的 ELSER 供我们进行语义搜索。ELSER 是一种稀疏向量的搜索方法。我们无需对它做任何的微调及训练。它是一种 out-of-domain 的模型。目前它仅对英文进行支持。希望将来它能对其它的语言支持的更好。更多关于 ELSER 的知识&#xff0c;请参阅文章 “Elas…

YOLOv8改进 | 细节创新篇 | iAFF迭代注意力特征融合助力多目标细节涨点

一、本文介绍 本文给大家带来的改进机制是iAFF&#xff08;迭代注意力特征融合&#xff09;&#xff0c;其主要思想是通过改善特征融合过程来提高检测精度。传统的特征融合方法如加法或串联简单&#xff0c;未考虑到特定对象的融合适用性。iAFF通过引入多尺度通道注意力模块(我…

winserver2008 r2服务器iis配置支持flv,f4v,mp4格式视频

很多政府单位网站一直在使用WIN服务器&#xff0c;大部分网站都使用多年基本使用.NET或者CMS系统建站&#xff0c;系统环境也一直是老版本&#xff0c;今天在维护过程中又出现了新问题&#xff0c;上传的MP4文件不支持网站上播放&#xff0c;顺便也分享下解决过程。当我们架设的…