C++的单例模式

忘记之前有没有写过单例模式了。
再记录一下:
我使用的代码:

#ifndef SINGLETON_MACRO_HPP
#define SINGLETON_MACRO_HPP#define SINGLETON_DECL(class_name) \
public: \static class_name& instance() { \static class_name s_instance; \return s_instance; \} \
private: \class_name();\class_name(const class_name&) = delete; \class_name& operator=(const class_name&) = delete;#endif // SINGLETON_MACRO_HPP

双锁单例:

#include <iostream>
#include <mutex>class Singleton {
private:static Singleton* instance;static std::mutex mtx;// 私有化构造函数,确保不能在类外部进行实例化Singleton() {}public:// 删除复制构造函数和复制赋值操作符Singleton(const Singleton& other) = delete;Singleton& operator=(const Singleton& other) = delete;static Singleton* getInstance() {if (instance == nullptr) { // 判断实例是否已经被创建,提高效率std::lock_guard<std::mutex> lock(mtx); // 锁定if (instance == nullptr) { // 再次检查,以确保线程安全instance = new Singleton();}}return instance;}
};// 初始化静态成员
Singleton* Singleton::instance = nullptr;
std::mutex Singleton::mtx;int main() {Singleton* s1 = Singleton::getInstance();Singleton* s2 = Singleton::getInstance();if (s1 == s2) {std::cout << "Both instances are identical." << std::endl;} else {std::cout << "Instances are different." << std::endl;}return 0;
}

单例模式的不同实现方式各有优缺点

双检锁(Double Checked Locking):

优点:
线程安全。
在实例已经被创建之后,直接返回实例,避免了每次获取实例时都需要获取锁的开销。
缺点:
代码相对复杂。
在某些老的编译器或硬件架构上,双检锁可能无法正常工作,可能需要内存屏障或其他同步机制。

静态局部变量(Meyers’ Singleton):
class Singleton {
public:static Singleton& getInstance() {static Singleton instance;return instance;}
private:Singleton() {}
};

优点:
线程安全(在 C++11 及以后的版本中)。
代码简单、清晰。
延迟初始化:只有在首次调用 getInstance 时,实例才会被创建。
缺点:
对于老的 C++ 标准(C++11 之前),这种方法可能不是线程安全的。

饿汉式:
class Singleton {
private:static Singleton instance;Singleton() {}
public:static Singleton& getInstance() {return instance;}
};

优点:
线程安全,因为实例在程序开始时就已经被初始化。
代码简单。
缺点:
实例在程序开始时就被创建,即使它从未被使用,可能会导致不必要的资源占用或初始化开销。

懒汉式(简单):
class Singleton {
private:static Singleton* instance;Singleton() {}
public:static Singleton* getInstance() {if (!instance) {instance = new Singleton();}return instance;}
};

优点:
实现简单。
延迟初始化,只在首次获取实例时创建。
缺点:
非线程安全。如果多个线程同时尝试创建实例,可能导致多个实例被创建。

在实际的使用场景中,要根据具体的需求和上下文来选择合适的实现方法。例如,如果线程安全性很重要,那么使用双检锁或C++11及以后版本的静态局部变量方法可能更合适。

最后问题:我用的是什么模式??

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

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

相关文章

【UE 材质】实现方形渐变、中心渐变材质

步骤 一、实现方形渐变 1. 新建一个材质&#xff0c;材质域选择“后期处理” 2. 通过“Mask”节点单独获取R、G通道&#xff0c;可以看到R通道是从左到右0~1之间的变化&#xff0c;对应U平铺 可以看到G通道是从上到下0~1之间的变化&#xff0c;对应V平铺 3. 完善如下节点 二、…

vim 使用/进行关键字搜索,跳转到下一个搜索结果的快捷键

在命令行中使用 / 或 ? 向下或向上搜索指定的字符&#xff0c;字符可手动输入 或 粘贴指定寄存器里的字符输入。通过 n 或 N 继续原方向或反向跳转到下一个匹配到的位置。 此外还可以同时进行多个匹配(关键字)的搜索&#xff0c;不同匹配项之间使用\|隔开即可。只要找到满足这…

里氏替换原则在继承关系中子类对父类方法的重写(覆盖)或重载时应遵循的规则

什么是里氏替换原则&#xff1a;只要父类能出现的地方子类就可以出现&#xff0c;而且 替换为子类也不会产生任何错误或异常&#xff0c;使用者可能根本就不需要知道是父类还是子类。但是&#xff0c;反过来就不行了&#xff0c;有子类出现的地方&#xff0c;父类未必就能适应。…

非关系型数据库Redis的安装

一、关系型数据库与非关系型数据库的区别&#xff1a;---------面试高频率问题 1、首先了解一下 什么是关系型数据库&#xff1f; 关系型数据库最典型的数据结构是表&#xff0c;由二维表及其之间的联系所组成的一个数据组织。 优点&#xff1a; 易于维护&#xff1a;都是使用…

2023年高教社杯数学建模思路 - 案例:最短时间生产计划安排

文章目录 0 赛题思路1 模型描述2 实例2.1 问题描述2.2 数学模型2.2.1 模型流程2.2.2 符号约定2.2.3 求解模型 2.3 相关代码2.4 模型求解结果 建模资料 0 赛题思路 &#xff08;赛题出来以后第一时间在CSDN分享&#xff09; https://blog.csdn.net/dc_sinor?typeblog 最短时…

数据分析作业2

中国在 2020 年开展第七次全国人口普查&#xff0c;截止 2021 年 5 月 11 日普查结果公布&#xff0c;全国人口共1411778724人。单从数据表格看相关数据不够直观&#xff0c;需要进行数据可视化展示&#xff0c;方便查看数据结果。 任务一&#xff1a;链接 MySQL 数据库&#x…

【C++设计模式】依赖倒转原则

2023年8月30日&#xff0c;周三上午 目录 概述含义举个简单的例子传统做法使用依赖倒转原则代码说明再举一个具体的例子以生活为例 概述 依赖倒转原则(Dependency Inversion Principle,DIP)是面向对象设计中的一个基本原则。 含义 高层模块不应该依赖低层模块,两者都应该依…

npm报错sass

1.删除node模块 2.删除node-sass&#xff1a; npm uninstall node-sass 3.重新下载对应版本node-sass&#xff1a; npm i node-sass7.0.3&#xff08;指定版本 控制台报错什么版本就写什么版本&#xff09; 4.再运行项目 或者

jdk-8u371-linux-x64.tar.gz jdk-8u371-windows-x64.exe 【jdk-8u371】 全平台下载

jdk-8u371 全平台下载 jdk-8u371-windows-x64.exejdk-8u371-linux-x64.rpmjdk-8u371-linux-x64.tar.gzjdk-8u371-macosx-x64.dmgjdk-8u371-linux-aarch64.tar.gz 下载地址 迅雷云盘 链接&#xff1a;https://pan.xunlei.com/s/VNdLL3FtCnh45nIBHulh_MDjA1?pwdw4s6 百度…

C语言:截断+整型提升练习

详情关于整型提升与截断见文章&#xff1a;《C语言&#xff1a;整型提升》 一、代码一 int main() { char a -1; signed char b -1; unsigned char c -1; printf("%d %d %d", a, b, c); return 0; } 求输出结果 解析如下代码&#xff1a; int mai…

基于Matlab实现生活中的图像信号分类(附上源码+数据集)

在我们的日常生活中&#xff0c;我们经常会遇到各种各样的图像信号&#xff0c;例如照片、视频、图标等等。对这些图像信号进行分类和识别对于我们来说是非常有用的。在本文中&#xff0c;我将介绍如何使用Matlab来实现生活中的图像信号分类。 文章目录 介绍源码数据集下载 介…

738.单调递增的数字 ,968.监控二叉树 +贪心总结

738.单调递增的数字 示例&#xff1a;如将322变成成单调递增的最大数字即299,如3442变成3399 首先要将n转换成字符数组&#xff0c; 其次遍历数组进行两次判断&#xff1a; 第一次是遍历数字时求当前最大的数字max。然后只在max<arr[i]的时候才更新max和对应的下标idx 第二…

Ajax与jQuery

目录 Ajax是一种异步无刷新的技术 Ajax的优点&#xff1a; 可以无需刷新页面与服务器端进行通信允许根据用户事件来更新部分页面内容 Ajax的缺点&#xff1a; 没有浏览历史&#xff0c;不能回退存在跨域问题&#xff08;同源&#xff09;SEO&#xff08;搜索引擎优化&#x…

Lambda表达式第一版

1、匿名内部类 package com.lambda;import java.util.Arrays; import java.util.Comparator;public class LambdaDemo1 {public static void main(String[] args) {Integer[] arr {2, 3, 1, 5, 6, 7, 8, 4, 9};Arrays.sort(arr, new Comparator<Integer>() {Overridepub…

什么是伪类链(Pseudo-class Chaining)?

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ Pseudo-class Chaining⭐ 写在最后 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 记得点击上方或者右侧链接订阅本专栏哦 几何带你启航前端之旅 欢迎来到前端入门之旅&#xff01;这个专栏是为那些对Web开发感兴趣、刚刚…

(十九)大数据实战——Flume数据采集框架安装部署

前言 本节内容我们主要介绍一下大数据数据采集框架flume的安装部署&#xff0c;Flume 是一款流行的开源分布式系统&#xff0c;用于高效地采集、汇总和传输大规模数据。它主要用于处理大量产生的日志数据和事件流。Flume 支持从各种数据源&#xff08;如日志文件、消息队列、数…

Redis数据库持久化---RDB(Redis DataBase)概念与实操

一、概念 1redis提供了两种持久化的方式&#xff0c;分别是RDB&#xff08;Redis DataBase&#xff09;和AOF&#xff08;Append Only File&#xff09;。 RDB&#xff08;Redis DataBase&#xff09;&#xff1a;是在不同的时间点&#xff0c;将redis存储的数据生成快照并存…

C++ 学习系列 -- 智能指针 make_shared 与 make_unique

一 make_shared 1.1 make_shared 是什么&#xff1f; c 11 中 引入了智能指针 shared_ptr&#xff0c;以及一个模板函数 make_shared 来生成一个制定类型的 shared_ptr。 1.2 引入 make_shared &#xff0c;解决了什么问题&#xff1f; make_shared的引入&#xff0c;主…

【计算机硬件CPU】

【计算机硬件CPU】 1、计算机硬件的五大单元2、一切设计的起点&#xff1a; CPU 的架构3、精简指令集 &#xff08;Reduced Instruction Set Computer, RISC&#xff09;4、复杂指令集&#xff08;Complex Instruction Set Computer, CISC&#xff09;5、例题&#xff1a;最新的…

Vue框架--Vue中el和data的两种写法

data与el的2种写法 1.el有2种写法 (1).new Vue时候配置el属性。 (2).先创建Vue实例&#xff0c;随后再通过vm.$mount(#root)指定el的值。 2.data有2种写法 (1).对象式 (2).函数式 如何选择&#xff1a;目前哪种写法都可以&#xff0c;以后学习到组件时&#xff…