当前位置: 首页 > news >正文

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懒汉式单例模式的写法&#xff0c;大家都很熟悉。早期的设计模式中有代码示例。比如&#xff1a; class Singleton {private: static Singleton *instance;public: static Singleton *getInstance() {if (NULL instance)instance new Singleton();return instanc…...

Gartner《2024中国安全技术成熟度曲线》AI安全助手代表性产品:开发者安全助手D10

海云安关注到&#xff0c;近日&#xff0c;国际权威研究机构Gartner发布了《2024中国安全技术成熟度曲线》(Hype Cycle for Security in China,2024)报告。 在此次报告中&#xff0c;安全技术成熟度曲线将安全周期划分为技术萌芽期&#xff08;Innovation Trigger&#xff09;…...

奇安信椒图--服务器安全管理系统(云锁)

奇安信椒图–服务器安全管理系统&#xff08;云锁&#xff09; 椒图 奇安信服务器安全管理系统是一款符合Gartner定义的CWPP&#xff08;云工作负载保护平台&#xff09;标准、EDR&#xff08;终端检测与响应&#xff09;、EPP终端保护平台&#xff08;终端保护平台&#xff…...

pointer-events,添加水印的一个小小点

场景&#xff1a;平平无奇一个水印图&#xff0c;这类功能实现&#xff1a;就是覆盖在整个可视div后&#xff0c;又加了一个div&#xff08;使用定位canvas画一个水印图充当背景&#xff09;&#xff0c;可时我好奇的是&#xff0c;我使用控制台&#xff0c;选择对应的元素时&a…...

微服务--认识微服务

微服务架构的演变 1. 单体架构&#xff08;Monolithic&#xff09; 阶段描述&#xff1a;在单体应用时代&#xff0c;整个应用程序被设计为一个项目&#xff0c;并在一个进程内运行。这种架构方式开发简单&#xff0c;便于集中管理&#xff0c;但随着应用的复杂化&#xff0c…...

【docker】docker 镜像仓库的管理

Docker 仓库&#xff08; Docker Registry &#xff09; 是用于存储和分发 Docker 镜像的集中式存储库。 它就像是一个大型的镜像仓库&#xff0c;开发者可以将自己创建的 Docker 镜像推送到仓库中&#xff0c;也可以从仓库中拉取所需的镜像。 Docker 仓库可以分为公共仓…...

第L2周:机器学习-线性回归

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 目标&#xff1a; 学习简单线性回归模型和多元线性回归模型通过代码实现&#xff1a;通过鸢尾花花瓣长度预测花瓣宽度 具体实现&#xff1a; &#xff08;一&…...

SpringMVC拦截器深度解析与实战

引言 Spring MVC作为Spring框架的核心模块之一&#xff0c;主要用于构建Web应用程序和RESTful服务。在Spring MVC中&#xff0c;拦截器&#xff08;Interceptor&#xff09;是一种强大的机制&#xff0c;它允许开发者在请求处理流程的特定点插入自定义代码&#xff0c;实现诸如…...

直线上最多的点数

优质博文&#xff1a;IT-BLOG-CN 题目 给你一个数组points&#xff0c;其中points[i] [xi, yi]表示X-Y平面上的一个点。求最多有多少个点在同一条直线上。 示例 1&#xff1a; 输入&#xff1a;points [[1,1],[2,2],[3,3]] 输出&#xff1a;3 示例 2&#xff1a; 输入&am…...

经济管理专业数据库介绍

本文介绍了四个经济管理专业数据库&#xff1a;国研网全文数据库、EPS数据平台、中经网、Emerald全文期刊库&#xff08;管理学&#xff09;。 一、国研网全文数据库 国研网是国务院发展研究中心主管、北京国研网信息有限公司承办的大型经济类专业网站。国研网教育版”是国研…...

【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幸存的最古老的两个命令行工具&#xff0c;其实我从来不认为Exp/Imp是一种好的备份方式&#xff0c;正确的说法是Exp/Imp只能是一个好的转储工具&#xff0c;特别是在小型数据库的转储&#xff0c;表空间的迁移&#xff0c;表的抽取&#xff0c;检测逻辑和物理…...

中国各银行流动性比例数据(2000-2022年)

介绍中国银行业2000年至2022年间的流动性比例数据&#xff0c;涵盖500多家银行&#xff0c;包括城市商业银行、城镇银行、大型商业银行、股份制银行、民营银行、农村合作银行、农村商业银行、农村信用社等。这些数据对于理解中国银行业的流动性状况至关重要&#xff0c;有助于投…...

MACOS安装配置前端开发环境

官网下载安装Mac版本的谷歌浏览器以及VS code代码编辑器&#xff0c;还有在App Store中直接安装Xcode&#xff08;里面自带git&#xff09;&#xff1b; node.js版本管理器nvm的下载安装如下&#xff1a; 参考B站&#xff1a;https://www.bilibili.com/video/BV1M54y1N7fx/?sp…...

Docker 配置国内镜像源

由于 GFW 的原因&#xff0c;在下载镜像的时候&#xff0c;经常会出现下载失败的情况&#xff0c;此时就可以使用国内的镜像源。 什么是镜像源&#xff1a;简单来说就是某个组织&#xff08;学校、公司、甚至是个人&#xff09;先通过某种手段将国外的镜像下载下来&#xff0c;…...

AI模块在人工智能中扮演着什么样的角色

AI模块在人工智能&#xff08;AI&#xff09;中扮演着核心和关键的角色。它们是构成AI系统的基础单元&#xff0c;负责实现AI系统的各种智能功能。以下是AI模块在人工智能中扮演的具体角色&#xff1a; 功能实现的核心&#xff1a;AI模块集成了实现特定智能功能所需的算法、数据…...

VM Workstation虚拟机AlmaLinux 9.4操作系统安装(桌面版安装详细教程)(宝塔面板的安装),填补CentOS终止支持维护的空白

目录 AlmaLinux介绍 AlmaLinux操作系统的安装 1、下载镜像文件 2、新建虚拟机 &#xff08;1&#xff09;点击创建新的虚拟机 &#xff08;2&#xff09;打开虚拟机向导后&#xff0c;选择“自定义”安装&#xff0c;然后点击“下一步” &#xff08;3&#xff09;选择虚…...

【学习笔记】卫星通信NTN 3GPP标准化进展分析(三)- 3GPP Release17 内容

一、引言&#xff1a; 本文来自3GPP Joern Krause, 3GPP MCC (May 14,2024) Non-Terrestrial Networks (NTN) (3gpp.org) 本文总结了NTN标准化进程以及后续的研究计划&#xff0c;是学习NTN协议的入门。 【学习笔记】卫星通信NTN 3GPP标准化进展分析&#xff08;一&#xff…...

【SQL】常见语句合集

SQL常见语句合集 一. 新建表1.1 语句1.2 结果 二. 新增数据2.1 语句2.2 结果 三. 新增字段列3.1 语句3.2 结果3.3 扩展 四. 更新指定数据4.1 语句4.2 结果 五. 更新指定列5.1 语句&#xff08;长度&#xff09; 六. 删除字段列6.1 语句 七. 删除指定数据7.1 语句 八. 查询 一. …...

Cozer必备!一站式解锁扣子全网最全插件集锦(三)

俗话说&#xff0c;工欲善其事必先利其器&#xff01; 用过Coze的朋友都知道&#xff0c;插件在Coze里的重要性。插件库就相当于武器库&#xff0c;一个好的插件&#xff0c;就相当于一件趁手的兵器&#xff0c;可以让你事半功倍&#xff01; 程哥精心整理了Coze最常用和好用…...

生成xcframework

打包 XCFramework 的方法 XCFramework 是苹果推出的一种多平台二进制分发格式&#xff0c;可以包含多个架构和平台的代码。打包 XCFramework 通常用于分发库或框架。 使用 Xcode 命令行工具打包 通过 xcodebuild 命令可以打包 XCFramework。确保项目已经配置好需要支持的平台…...

视频字幕质量评估的大规模细粒度基准

大家读完觉得有帮助记得关注和点赞&#xff01;&#xff01;&#xff01; 摘要 视频字幕在文本到视频生成任务中起着至关重要的作用&#xff0c;因为它们的质量直接影响所生成视频的语义连贯性和视觉保真度。尽管大型视觉-语言模型&#xff08;VLMs&#xff09;在字幕生成方面…...

C# 类和继承(抽象类)

抽象类 抽象类是指设计为被继承的类。抽象类只能被用作其他类的基类。 不能创建抽象类的实例。抽象类使用abstract修饰符声明。 抽象类可以包含抽象成员或普通的非抽象成员。抽象类的成员可以是抽象成员和普通带 实现的成员的任意组合。抽象类自己可以派生自另一个抽象类。例…...

微信小程序云开发平台MySQL的连接方式

注&#xff1a;微信小程序云开发平台指的是腾讯云开发 先给结论&#xff1a;微信小程序云开发平台的MySQL&#xff0c;无法通过获取数据库连接信息的方式进行连接&#xff0c;连接只能通过云开发的SDK连接&#xff0c;具体要参考官方文档&#xff1a; 为什么&#xff1f; 因为…...

Android 之 kotlin 语言学习笔记三(Kotlin-Java 互操作)

参考官方文档&#xff1a;https://developer.android.google.cn/kotlin/interop?hlzh-cn 一、Java&#xff08;供 Kotlin 使用&#xff09; 1、不得使用硬关键字 不要使用 Kotlin 的任何硬关键字作为方法的名称 或字段。允许使用 Kotlin 的软关键字、修饰符关键字和特殊标识…...

SAP学习笔记 - 开发26 - 前端Fiori开发 OData V2 和 V4 的差异 (Deepseek整理)

上一章用到了V2 的概念&#xff0c;其实 Fiori当中还有 V4&#xff0c;咱们这一章来总结一下 V2 和 V4。 SAP学习笔记 - 开发25 - 前端Fiori开发 Remote OData Service(使用远端Odata服务)&#xff0c;代理中间件&#xff08;ui5-middleware-simpleproxy&#xff09;-CSDN博客…...

日常一水C

多态 言简意赅&#xff1a;就是一个对象面对同一事件时做出的不同反应 而之前的继承中说过&#xff0c;当子类和父类的函数名相同时&#xff0c;会隐藏父类的同名函数转而调用子类的同名函数&#xff0c;如果要调用父类的同名函数&#xff0c;那么就需要对父类进行引用&#…...

在 Visual Studio Code 中使用驭码 CodeRider 提升开发效率:以冒泡排序为例

目录 前言1 插件安装与配置1.1 安装驭码 CodeRider1.2 初始配置建议 2 示例代码&#xff1a;冒泡排序3 驭码 CodeRider 功能详解3.1 功能概览3.2 代码解释功能3.3 自动注释生成3.4 逻辑修改功能3.5 单元测试自动生成3.6 代码优化建议 4 驭码的实际应用建议5 常见问题与解决建议…...

【java面试】微服务篇

【java面试】微服务篇 一、总体框架二、Springcloud&#xff08;一&#xff09;Springcloud五大组件&#xff08;二&#xff09;服务注册和发现1、Eureka2、Nacos &#xff08;三&#xff09;负载均衡1、Ribbon负载均衡流程2、Ribbon负载均衡策略3、自定义负载均衡策略4、总结 …...

如何做好一份技术文档?从规划到实践的完整指南

如何做好一份技术文档&#xff1f;从规划到实践的完整指南 &#x1f31f; 嗨&#xff0c;我是IRpickstars&#xff01; &#x1f30c; 总有一行代码&#xff0c;能点亮万千星辰。 &#x1f50d; 在技术的宇宙中&#xff0c;我愿做永不停歇的探索者。 ✨ 用代码丈量世界&…...