深入解析C++单例模式:从基础到线程安全的高效实现

news/2024/9/17 23:50:55/ 标签: 开发语言, c++, qt

引言

在C++开发中,单例模式(Singleton Pattern) 是一种常见且重要的设计模式。它确保类的实例在整个程序生命周期中唯一,并提供一个全局访问点。这在日志管理、配置管理等场景中尤为常见。本篇博客将带你深入了解单例模式的实现原理,并介绍如何在多线程环境下实现线程安全的单例模式。

什么是单例模式?

单例模式是一种设计模式,其核心思想是确保某个类只能有一个实例,并提供一个全局的访问点。其应用场景包括:

  • 配置管理器:在系统中需要统一的配置管理时,可以使用单例确保配置对象的唯一性。
  • 日志管理器:在程序中记录日志时,日志系统应该是全局的,避免多个日志管理器造成混乱。

单例模式的关键特性

  1. 唯一性:单例模式确保某个类的实例只有一个,任何时候获取的都是同一个实例。
  2. 全局访问点:提供一个全局访问方法,通过它可以获取这个唯一的实例。
  3. 延迟初始化:实例在第一次使用时创建,避免了程序启动时的资源浪费。

单例模式的基本实现

让我们从最简单的单例模式实现开始。以下是一个经典的C++单例模式代码:

#include <iostream>class Singleton {
private:// 构造函数私有化,防止外部直接实例化Singleton() {std::cout << "Singleton 构造函数被调用" << std::endl;}// 禁用复制构造和赋值操作符Singleton(const Singleton&) = delete;Singleton& operator=(const Singleton&) = delete;public:// 提供静态方法获取唯一实例static Singleton& getInstance() {static Singleton instance;  // 静态局部变量,保证只初始化一次return instance;}void showMessage() {std::cout << "这是单例模式的实例" << std::endl;}
};int main() {Singleton& instance1 = Singleton::getInstance();instance1.showMessage();Singleton& instance2 = Singleton::getInstance();instance2.showMessage();return 0;
}

解释:

  • 私有构造函数:构造函数是私有的,防止外部使用 new 来实例化对象。
  • 静态成员函数getInstance 方法返回类的唯一实例。
  • 静态局部变量:静态局部变量 instance 只会在第一次调用时初始化,确保了唯一性和延迟初始化。

C++11中的线程安全单例模式

在多线程环境下,如果多个线程同时调用 getInstance(),可能会引发竞争条件,导致创建多个实例。幸运的是,C++11引入了线程安全的静态局部变量初始化机制,这让我们可以轻松实现线程安全的单例模式:

class Singleton {
private:Singleton() {std::cout << "线程安全的 Singleton 构造函数" << std::endl;}Singleton(const Singleton&) = delete;Singleton& operator=(const Singleton&) = delete;public:static Singleton& getInstance() {static Singleton instance;return instance;}void showMessage() {std::cout << "线程安全的单例实例" << std::endl;}
};

C++11 的静态变量特性:

  • C++11 规范保证静态局部变量的初始化是线程安全的。因此,在没有复杂同步机制的情况下,可以安全地在多线程环境中使用静态局部变量实现单例模式。

双重检查锁定(DCLP)实现懒汉式单例

为了进一步优化性能,有时我们会使用双重检查锁定(Double-Checked Locking Pattern,DCLP)。这种方式在懒汉式单例的基础上,通过加锁确保线程安全。

#include <iostream>
#include <mutex>class Singleton {
private:Singleton() {std::cout << "懒汉式 Singleton 构造函数" << std::endl;}static Singleton* instance;static std::mutex mtx;public:static Singleton* getInstance() {if (instance == nullptr) {  // 第一次检查std::lock_guard<std::mutex> lock(mtx);  // 加锁if (instance == nullptr) {  // 第二次检查instance = new Singleton();}}return instance;}void showMessage() {std::cout << "线程安全的懒汉式单例" << std::endl;}
};// 静态成员初始化
Singleton* Singleton::instance = nullptr;
std::mutex Singleton::mtx;

单例模式的优缺点

优点:

  1. 控制实例数量:确保全局只有一个实例,避免资源浪费。
  2. 全局访问:提供全局访问接口,方便统一管理资源。
  3. 延迟初始化:可以在首次调用时创建实例,节省系统资源。

缺点:

  1. 测试困难:由于单例是全局对象,可能会影响单元测试的独立性。
  2. 不易扩展:单例模式限制了继承和多态的使用,扩展性较差。

总结

单例模式在C++开发中具有重要的意义,尤其是在需要唯一对象实例的场景中,能够有效节省资源,确保程序的稳定性。通过本文的介绍,您应该能够轻松理解和实现C++中的单例模式,并掌握在多线程环境下的线程安全实现。

你在项目中使用过单例模式吗?有哪些实际的应用场景?欢迎在评论区分享你的经验!


http://www.ppmy.cn/news/1525098.html

相关文章

单例模式的总结

常规模式:有属性/构造方法/普通方法&#xff0c;也可以在类中执行主方法&#xff0c;也可以在test类中执行主方法 单例模式是什么&#xff1f; 单例模式&#xff1a;类只有1个对象&#xff1b;保证一个类仅有一个实例&#xff0c;并提供一个访问它的全局访问点。单例模式是在内…

uniapp uni-table合并单元格

视图层 <uni-table border stripe emptyText"暂无更多数据" class"table_x"><!-- 表头行 --><uni-tr><uni-th align"center">患者姓名</uni-th><uni-th align"center">透析方式</uni-th>&…

常用设计模式的通俗解释和c语言实现

单例模式 单例模式确保一个类只有一个实例,并提供一个全局访问点。 通俗解释:想象一个公司只能有一个CEO。无论你如何尝试创建新的CEO,你总是会得到同一个人。 #include <stdio.h> #include <stdlib.h>typedef struct {int data; } Singleton;static Singleton* i…

设计模式 23 访问者模式

设计模式 23 创建型模式&#xff08;5&#xff09;&#xff1a;工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式结构型模式&#xff08;7&#xff09;&#xff1a;适配器模式、桥接模式、组合模式、装饰者模式、外观模式、享元模式、代理模式行为型模式&#xff…

Vue3+TS项目给el-button统一封装一个点击后转圈效果的钩子函数按钮防抖

前言 每个按钮都要单独定义一个loading变量&#xff0c;并且在接口请求前修改为true&#xff0c;接口响应后再修改为false&#xff0c;封装后这段重复的逻辑就可以统一管理不用每次都写一遍了。 效果 新建一个公共的src\common.ts import { ref } from "vue"expor…

【有啥问啥】探索扫地机器人中的 SLAM 算法:原理、实现与未来展望

探索扫地机器人中的 SLAM 算法&#xff1a;原理、实现与未来展望 随着智能家居的普及&#xff0c;扫地机器人逐渐成为日常生活中的常见家电。其自主导航能力使得它能够在复杂的家庭环境中高效完成清洁任务&#xff0c;而这背后的核心技术之一就是 SLAM&#xff08;Simultaneou…

git的快速合并fast-forward merge详解

文章目录 1. 什么是快进合并&#xff1f;2. 快进合并的前提条件3. 快进合并的工作原理3.1 示例场景&#xff1a;3.2 使用命令&#xff1a;3.3 快进合并的视觉效果&#xff1a; 4. 快进合并的优点5. 快进合并的缺点6. 快进合并 vs 非快进合并6.1 非快进合并&#xff1a;6.2 非快…

【Linux】ps -ef 与 ps aux 的区别及 “|” “grep” 的详解

前言&#xff1a;虽然 ps -ef 与 ps aux 命令都能查看进程运行情况&#xff0c;但两者之间还是有一些细致区别。 一、格式与输出 1、ps -ef/ps -Af&#xff1a; -e是显示所有进程&#xff0c;包括其他用户的进程。-A属于-e别名&#xff0c;功能相同。 -f &#xff1a;显示更…

Android TextView 学习备忘

1.android:gravity 与 android:layout_gravity&#xff1a; Android TextView文本位置_mob649e8166858d的技术博客_51CTO博客https://blog.51cto.com/u_16175509/8597723 2.设置字体样式&#xff1a; android:fontFamily"font/my_custom_font"android:textStyle&qu…

Android SystemUI组件(05)状态栏-系统状态图标显示管理

该系列文章总纲链接&#xff1a;专题分纲目录 Android SystemUI组件 本章关键点总结 & 说明&#xff1a; 说明&#xff1a;本章节持续迭代之前章节的思维导图&#xff0c;主要关注下方 SystemBars分析中状态栏中的部分-系统状态图标显示&管理 即可。 1 系统状态图标显…

SenseGlove机器臂遥操作控制:技术优势与高危作业安全保障

在追求高效与安全的工业时代&#xff0c;高危作业任务始终是行业发展的一大障碍。SenseGlove力反馈手套机器臂遥操作应用案例的出现&#xff0c;凭借其独特的技术优势&#xff0c;为解决这一难题提供了创新性解决方案。 一、技术优势 高精度的力反馈技术&#xff1a;SenseGlove…

CTF——简单的《WEB》

文章目录 一、WEB1、easysql2、baby_web3、baby_sql4、upload_easy5、easygame拓展1.1拓展1.2 6、ht_ssti7、包容乃大 一、WEB 1、easysql 题目描述&#xff1a; sql注入漏洞 1.常用的sql注入测试语句 2.sql注入bypass 解题思路 这边提示基本给的也很完整的&#xff0c;不…

基于中心点的目标检测方法CenterNet—CVPR2019

Anchor Free目标检测算法—CenterNet Objects as Points论文解析 Anchor Free和Anchor Base方法的区别在于是否在检测的过程中生成大量的先验框。CenterNet直接预测物体的中心点的位置坐标。 CenterNet本质上类似于一种关键点的识别。识别的是物体的中心点位置。 有了中心点之…

关于Python爬虫的基础知识

爬虫是一种自动获取网页内容的程序或工具。以下是一些关于爬虫的基础知识&#xff1a; 一、爬虫的工作原理 发送请求&#xff1a; 爬虫首先向目标网站发送 HTTP 请求&#xff0c;就像你在浏览器中输入网址并访问一样。请求中包含了一些信息&#xff0c;如请求方法&#xff08;…

Spring Boot集成Akka Stream快速入门Demo

1.什么是Akka Stream&#xff1f; Akka Streams是一个用于处理和传输元素序列的库。它建立在Akka Actors之上&#xff0c;使流的摄入和处理变得简单。由于它是建立在Akka Actors之上的&#xff0c;它为Akka现有的actor模型提供了一个更高层次的抽象。Akka流由3个主要部分组成-…

Linux平台屏幕|摄像头采集并实现RTMP推送两种技术方案探究

技术背景 随着国产化操作系统的推进&#xff0c;市场对国产化操作系统下的生态构建&#xff0c;需求越来越迫切&#xff0c;特别是音视频这块&#xff0c;今天我们讨论的是如何在linux平台实现屏幕|摄像头采集&#xff0c;并推送至RTMP服务。 我们知道&#xff0c;Linux平台&…

洛谷刷题之B2089 数组逆序重存放

数组逆序重存放 题目入口 题目描述 将一个数组中的值按逆序重新存放。例如&#xff0c;原来的顺序为 8 , 6 , 5 , 4 , 1 8,6,5,4,1 8,6,5,4,1。要求改为 1 , 4 , 5 , 6 , 8 1,4,5,6,8 1,4,5,6,8。 输入格式 输入为两行&#xff1a;第一行数组中元素的个数 n n n&#x…

比 GPT-4 便宜 187 倍的Mistral 7B (非广告)

Mistral 7B 是一种设计用来快速处理较长文本的人工智能模型。它采用了一些特别的技术来提高速度和效率&#xff0c;比如“分组查询注意力&#xff08;grouped-query attention&#xff09;”和“滑动窗口注意力&#xff08;sliding-window attention&#xff09;”。 这些技术…

UNI-APP 富文本编辑器,可以对图片、文字格式进行编辑和混排。

✍找了几篇文章对比了一下&#xff0c;大体都差不多各有各的说辞和见解,但是没有提供/style/editor-icon.css文件&#xff0c;找起来虽然说不算太麻烦&#xff0c;但是不够直接&#xff0c;又要花费时间去弄&#xff0c;虽然用的不是很多但是&#xff0c;我还是决定自己写一篇&…

第15-05章:获取运行时类的完整结构

我的后端学习大纲 我的Java学习大纲 6.1.第一组方法API: 1.API列表&#xff1a;java.lang.Class 类&#xff1a; 2.代码测试&#xff1a; public class ReflectionUtils{ puvblic static void main(String[] args){}// 第一组Testpublic void api_01{//上面截图的代码......…