c++懒汉式单例模式(Singleton)多种实现方式及最优比较
前言
关于C++懒汉式单例模式的写法,大家都很熟悉。早期的设计模式中有代码示例。比如:
class Singleton {private: static Singleton *instance;public: static Singleton *getInstance() {if (NULL == instance)instance = new Singleton();return instance;}
};
它的缺点:线程不安全,指针资源没有释放。
自从C++11推出后,单例模式有了更优秀的写法,下面来介绍下。
使用 std::call_once 实现
#include <iostream>
#include <mutex>
#include <memory>class Singleton {
private:Singleton() { std::cout << "Singleton constructed." << std::endl; }static std::once_flag initInstanceFlag;static std::unique_ptr<Singleton> instance;// 删除拷贝构造函数和赋值操作符Singleton(const Singleton&) = delete;Singleton& operator=(const Singleton&) = delete;public:static Singleton& getInstance() {std::call_once(initInstanceFlag, []() {instance.reset(new Singleton());});return *instance;}void someMethod() {std::cout << "Method of the singleton" << std::endl;}~Singleton() {std::cout << "Singleton destructed." << std::endl;}
};std::once_flag Singleton::initInstanceFlag;
std::unique_ptr<Singleton> Singleton::instance;// 使用示例
void threadFunction() {Singleton& singleton = Singleton::getInstance();singleton.someMethod();
}int main() {std::thread t1(threadFunction);std::thread t2(threadFunction);t1.join();t2.join();return 0;
}
优点:线程安全、内存安全。显式控制初始化过程,适合需要延迟初始化的场景。
使用局部静态变量实现(C++11及以后)
#include <iostream>
#include <memory>class Singleton {
private:Singleton() { std::cout << "Singleton constructed." << std::endl; }// 关闭拷贝构造函数、右值拷贝构造函数和赋值操作符Singleton(const Singleton&) = delete;Singleton(const Singleton &&) = delete;Singleton& operator=(const Singleton&) = delete;public:static Singleton& getInstance() {static Singleton instance;return instance;}void someMethod() {std::cout << "Method of the singleton" << std::endl;}~Singleton() {std::cout << "Singleton destructed." << std::endl;}
};// 使用示例
void threadFunction() {Singleton& singleton = Singleton::getInstance();singleton.someMethod();
}int main() {std::thread t1(threadFunction);std::thread t2(threadFunction);t1.join();t2.join();return 0;
}
优点:线程安全。代码最简洁,由C++11标准保证线程安全,适合大多数场景。
缺点:适用于不复杂的工程。因为如果静态类之间有依赖,可能会导致C++的一些未定义的行为。
Meyers 的版本
Scott Meyers 是 Effective C++系列的作者,他最早提供了简洁版本的 Singletion 模型。根据他提供的模型,可以写出线程安全又简单的单例模式。代码如下:
#include <stdio.h>class singleton {static singleton &instance() {static singleton instance;return instance;} // instancesingleton(const singleton &) = delete;singleton & operator = (const singleton &) = delete;private:singleton() {}~singleton() {}public:void out(){ printf("out\n"); }
}; // struct singletonint main() {singleton::instance().out();return 0;
}
缺点:单一的实例总是在 main() 开始之前被初始化的,该实现无法做到 lazyinit。
优化版本:
template<typename T>class singleton {public:static T &instance();singleton(const singleton &) = delete;singleton &operator=(const singleton) = delete;protected:singleton() = default;};template<typename T>inline T &singleton<T>::instance() {static const std::unique_ptr<T> instance{new T{token{}}};return *instance;}
优点:线程安全、内存安全。
鸿蒙单例实现
线程安全、内存安全、双重检测、延迟加载、支持lazyinit、实现懒汉式单例模板。当前在商业(鸿蒙手机操作系统)使用中,代码可靠。
使用说明,请点这里。
下面只展示DelayedSingleton实现示例。完整代码以及其它几种单例实现,请点这里。
补充说明:对于懒汉式单例模式双重检测,有的人嫌代码麻烦,将构造函数私有化来实现。这个大家自己去评价。其实也没几行代码。写上双重检测,逻辑上也是提醒大家代码实现的风险点。不算优化问题。论可靠,还是相信鸿蒙吧。
template<typename T>
class DelayedSingleton : public NoCopyable {
public:static std::shared_ptr<T> GetInstance();static void DestroyInstance();private:static std::shared_ptr<T> instance_; instance.static std::mutex mutex_;
};template<typename T>
std::shared_ptr<T> DelayedSingleton<T>::instance_ = nullptr;template<typename T>
std::mutex DelayedSingleton<T>::mutex_;template<typename T>
std::shared_ptr<T> DelayedSingleton<T>::GetInstance()
{if (instance_ == nullptr) {std::lock_guard<std::mutex> lock(mutex_);if (instance_ == nullptr) {std::shared_ptr<T> temp(new (std::nothrow) T);instance_ = temp;}}return instance_;
}template<typename T>
void DelayedSingleton<T>::DestroyInstance()
{std::lock_guard<std::mutex> lock(mutex_);if (instance_ != nullptr) {instance_.reset();instance_ = nullptr;}
}
相关文章:
c++懒汉式单例模式(Singleton)多种实现方式及最优比较
前言 关于C懒汉式单例模式的写法,大家都很熟悉。早期的设计模式中有代码示例。比如: class Singleton {private: static Singleton *instance;public: static Singleton *getInstance() {if (NULL instance)instance new Singleton();return instanc…...
Gartner《2024中国安全技术成熟度曲线》AI安全助手代表性产品:开发者安全助手D10
海云安关注到,近日,国际权威研究机构Gartner发布了《2024中国安全技术成熟度曲线》(Hype Cycle for Security in China,2024)报告。 在此次报告中,安全技术成熟度曲线将安全周期划分为技术萌芽期(Innovation Trigger)…...
奇安信椒图--服务器安全管理系统(云锁)
奇安信椒图–服务器安全管理系统(云锁) 椒图 奇安信服务器安全管理系统是一款符合Gartner定义的CWPP(云工作负载保护平台)标准、EDR(终端检测与响应)、EPP终端保护平台(终端保护平台ÿ…...
pointer-events,添加水印的一个小小点
场景:平平无奇一个水印图,这类功能实现:就是覆盖在整个可视div后,又加了一个div(使用定位canvas画一个水印图充当背景),可时我好奇的是,我使用控制台,选择对应的元素时&a…...
微服务--认识微服务
微服务架构的演变 1. 单体架构(Monolithic) 阶段描述:在单体应用时代,整个应用程序被设计为一个项目,并在一个进程内运行。这种架构方式开发简单,便于集中管理,但随着应用的复杂化,…...
【docker】docker 镜像仓库的管理
Docker 仓库( Docker Registry ) 是用于存储和分发 Docker 镜像的集中式存储库。 它就像是一个大型的镜像仓库,开发者可以将自己创建的 Docker 镜像推送到仓库中,也可以从仓库中拉取所需的镜像。 Docker 仓库可以分为公共仓…...
第L2周:机器学习-线性回归
🍨 本文为🔗365天深度学习训练营 中的学习记录博客🍖 原作者:K同学啊 目标: 学习简单线性回归模型和多元线性回归模型通过代码实现:通过鸢尾花花瓣长度预测花瓣宽度 具体实现: (一&…...
SpringMVC拦截器深度解析与实战
引言 Spring MVC作为Spring框架的核心模块之一,主要用于构建Web应用程序和RESTful服务。在Spring MVC中,拦截器(Interceptor)是一种强大的机制,它允许开发者在请求处理流程的特定点插入自定义代码,实现诸如…...
直线上最多的点数
优质博文:IT-BLOG-CN 题目 给你一个数组points,其中points[i] [xi, yi]表示X-Y平面上的一个点。求最多有多少个点在同一条直线上。 示例 1: 输入:points [[1,1],[2,2],[3,3]] 输出:3 示例 2: 输入&am…...
经济管理专业数据库介绍
本文介绍了四个经济管理专业数据库:国研网全文数据库、EPS数据平台、中经网、Emerald全文期刊库(管理学)。 一、国研网全文数据库 国研网是国务院发展研究中心主管、北京国研网信息有限公司承办的大型经济类专业网站。国研网教育版”是国研…...
【C++ Primer Plus习题】11.1
问题: 解答: main.cpp #include <iostream> #include <fstream> #include "Vector.h" #include <time.h> using namespace std; using namespace VECTOR;int main() {ofstream fout;fout.open("randwalk.txt");srand(time(0));double d…...
[数据库][oracle]ORACLE EXP/IMP的使用详解
导入/导出是ORACLE幸存的最古老的两个命令行工具,其实我从来不认为Exp/Imp是一种好的备份方式,正确的说法是Exp/Imp只能是一个好的转储工具,特别是在小型数据库的转储,表空间的迁移,表的抽取,检测逻辑和物理…...
中国各银行流动性比例数据(2000-2022年)
介绍中国银行业2000年至2022年间的流动性比例数据,涵盖500多家银行,包括城市商业银行、城镇银行、大型商业银行、股份制银行、民营银行、农村合作银行、农村商业银行、农村信用社等。这些数据对于理解中国银行业的流动性状况至关重要,有助于投…...
MACOS安装配置前端开发环境
官网下载安装Mac版本的谷歌浏览器以及VS code代码编辑器,还有在App Store中直接安装Xcode(里面自带git); node.js版本管理器nvm的下载安装如下: 参考B站:https://www.bilibili.com/video/BV1M54y1N7fx/?sp…...
Docker 配置国内镜像源
由于 GFW 的原因,在下载镜像的时候,经常会出现下载失败的情况,此时就可以使用国内的镜像源。 什么是镜像源:简单来说就是某个组织(学校、公司、甚至是个人)先通过某种手段将国外的镜像下载下来,…...
AI模块在人工智能中扮演着什么样的角色
AI模块在人工智能(AI)中扮演着核心和关键的角色。它们是构成AI系统的基础单元,负责实现AI系统的各种智能功能。以下是AI模块在人工智能中扮演的具体角色: 功能实现的核心:AI模块集成了实现特定智能功能所需的算法、数据…...
VM Workstation虚拟机AlmaLinux 9.4操作系统安装(桌面版安装详细教程)(宝塔面板的安装),填补CentOS终止支持维护的空白
目录 AlmaLinux介绍 AlmaLinux操作系统的安装 1、下载镜像文件 2、新建虚拟机 (1)点击创建新的虚拟机 (2)打开虚拟机向导后,选择“自定义”安装,然后点击“下一步” (3)选择虚…...
【学习笔记】卫星通信NTN 3GPP标准化进展分析(三)- 3GPP Release17 内容
一、引言: 本文来自3GPP Joern Krause, 3GPP MCC (May 14,2024) Non-Terrestrial Networks (NTN) (3gpp.org) 本文总结了NTN标准化进程以及后续的研究计划,是学习NTN协议的入门。 【学习笔记】卫星通信NTN 3GPP标准化进展分析(一ÿ…...
【SQL】常见语句合集
SQL常见语句合集 一. 新建表1.1 语句1.2 结果 二. 新增数据2.1 语句2.2 结果 三. 新增字段列3.1 语句3.2 结果3.3 扩展 四. 更新指定数据4.1 语句4.2 结果 五. 更新指定列5.1 语句(长度) 六. 删除字段列6.1 语句 七. 删除指定数据7.1 语句 八. 查询 一. …...
Cozer必备!一站式解锁扣子全网最全插件集锦(三)
俗话说,工欲善其事必先利其器! 用过Coze的朋友都知道,插件在Coze里的重要性。插件库就相当于武器库,一个好的插件,就相当于一件趁手的兵器,可以让你事半功倍! 程哥精心整理了Coze最常用和好用…...
别再手动画点了!用ArcGIS Pro的‘沿线生成点’工具,5分钟搞定街景采样点CSV
用ArcGIS Pro高效生成街景采样点的5个关键技巧 在数字化城市研究和街景分析中,获取均匀分布的采样点是基础但耗时的步骤。传统手动标注方法不仅效率低下,还容易引入人为误差。ArcGIS Pro的"沿线生成点"工具能自动化这一过程,但许多…...
如何用Sunshine打造个人专属的游戏云服务:从零开始搭建高性能串流服务器
如何用Sunshine打造个人专属的游戏云服务:从零开始搭建高性能串流服务器 【免费下载链接】Sunshine Self-hosted game stream host for Moonlight. 项目地址: https://gitcode.com/GitHub_Trending/su/Sunshine 厌倦了被高性能游戏主机束缚在固定位置&#x…...
Open UI5 源代码解析之886:OverflowToolbarButton.js
源代码仓库: https://github.com/SAP/openui5 源代码位置:src\sap.m\src\sap\m\OverflowToolbarButton.js OverflowToolbarButton.js 深度解析与项目作用说明 文件定位与总体价值 这个文件定义了一个控件:sap.m.OverflowToolbarButton。从代码体量看,它并不长,却属于…...
5步解锁Masa Mods全中文体验:从安装到精通的本地化指南
5步解锁Masa Mods全中文体验:从安装到精通的本地化指南 【免费下载链接】masa-mods-chinese 一个masa mods的汉化资源包 项目地址: https://gitcode.com/gh_mirrors/ma/masa-mods-chinese Masa Mods汉化资源包是解决Minecraft玩家语言障碍的关键工具…...
如何快速提升技术文档专业度:Obsidian代码美化插件终极指南
如何快速提升技术文档专业度:Obsidian代码美化插件终极指南 【免费下载链接】obsidian-better-codeblock Add title, line number to Obsidian code block 项目地址: https://gitcode.com/gh_mirrors/ob/obsidian-better-codeblock 还在为技术笔记中单调乏味…...
如何解决JAVA无人共享无人健身房物联网结合系统防尾随问题
在JAVA无人共享无人健身房物联网结合系统中,防尾随问题可通过AB门防尾随方案结合物联网技术、AI算法和JAVA后端逻辑实现,其核心在于双门互锁机制AI人数检测实时通信控制。以下是具体解决方案:一、系统架构设计硬件层:双门结构&…...
Gerrit与GitLab单向同步实战:配置详解与常见问题排查
1. 为什么需要Gerrit与GitLab单向同步? 在代码管理的工作流中,Gerrit和GitLab各自扮演着不同角色。Gerrit以强大的代码审核机制著称,而GitLab则更擅长作为Git仓库托管平台。很多团队既想保留GitLab现有的CI/CD流程,又希望引入Gerr…...
从零到一:Keil5环境搭建与STM32项目实战避坑指南
1. Keil5安装与基础配置 第一次接触Keil MDK的开发者,八成会在安装环节就踩坑。我当年用STM32F103C8T6做毕业设计时,光是解决xerces-c_3_0.dll缺失问题就折腾了一整天。这个经典错误其实有更稳妥的解决方案:除了将dll文件复制到System32目录…...
YOLOv11算法优化实战:从特征融合到动态推理的性能跃迁
1. YOLOv11算法核心优化方向 目标检测领域近年来最令人兴奋的进展之一,就是YOLO系列算法的持续进化。作为这个家族的最新成员,YOLOv11在保持实时性的同时,通过多项技术创新实现了检测精度的显著提升。但在实际工业应用中,我们发现…...
如何用智能工具彻底改变黑苹果配置:一站式自动化解决方案的革命性突破
如何用智能工具彻底改变黑苹果配置:一站式自动化解决方案的革命性突破 【免费下载链接】OpCore-Simplify A tool designed to simplify the creation of OpenCore EFI 项目地址: https://gitcode.com/GitHub_Trending/op/OpCore-Simplify 在技术爱好者的世界…...
