文章目录

  • 单例模式
  • 创建单例类
  • 饿汉式or懒汉式
  • 现代C++单例模式的主流实现方式——Meyer's Singleton
  • 使用 CRTP 模板化单例类


单例模式

单例模式是指程序中只需要一个实例化对象,在全局作用域或整个代码架构中,此对象只被实例化一次,就可以达到在整个程序生命周期中被使用的目的。假如程序中设计了单例模式类,但是在程序设计中实例化了多个对象,那么这些对象也只占用同一块地址空间,在代码中可以通过"%p"输出的内存地址看出,这些对象是唯一的实例。

创建单例类

如何保证类的实例有且仅有一个?
涉及一个类多对象操作的函数有以下几个:

  • 构造函数:创建一个新的对象
  • 拷贝构造函数:根据已有对象拷贝出一个新的对象
  • 拷贝赋值操作符重载函数:两个对象之间的赋值

为了把一个类可以实例化多个对象的路堵死,可以做如下处理:

  • 构造函数私有化,在类内部只调用一次,这个是可控的。
    • 由于使用者在类外部不能使用构造函数,所以在类内部创建的这个唯一的对象必须是静态的,这样就可以通过类名来访问了,为了不破坏类的封装,我们都会把这个静态对象的访问权限设置为私有的。
      在类中只有它的静态成员函数才能访问其静态成员变量,所以可以给这个单例类提供一个静态函数用于得到这个静态的单例对象。
  • 拷贝构造函数私有化或者禁用(使用 = delete)
  • 拷贝赋值操作符重载函数私有化或者禁用(从单例的语义上讲这个函数已经毫无意义,所以在类中不再提供这样一个函数,故将它也一并处理一下。)

在这里插入图片描述

// 定义一个单例模式的类
class Singleton
{
public:Singleton(const Singleton& obj) = delete;Singleton& operator=(const Singleton& obj) = delete;static Singleton* GetInstance(){return instance;}
private:Singleton() = default;static Singleton* instance;
};//静态成员变量只能在类外部初始化
Singleton* Singleton::instance = new Singleton();

饿汉式or懒汉式

饿汉模式 就是在类加载的时候立刻进行实例化,这样就得到了一个唯一的可用对象。
适用于内存大的场景,多线程调用没有线程安全问题。

懒汉模式 是在类加载的时候不去创建这个唯一的实例,而是在需要使用的时候再进行实例化。
适用于内存紧张的场景,多线程调用有线程安全问题。

参考文章:https://subingwen.cn/design-patterns/singleton/

现代C++单例模式的主流实现方式——Meyer’s Singleton

Meyer’s Singleton是典型的懒汉模式:

  • 线程安全(C++11 起):局部静态变量的初始化是线程安全的(编译器会自动加锁)。
  • 延迟初始化(Lazy Initialization):只有当 GetInstance() 第一次被调用时才会构造对象。
  • 自动资源管理:程序结束时,静态变量会自动析构(除非你使用了动态分配)。
  • 高效无拷贝:返回的是引用,不会产生拷贝,效率高。
class Singleton
{
public:Singleton(const Singleton& obj) = delete;Singleton& operator=(const Singleton& obj) = delete;static Singleton& GetInstance(){static Singleton instance;return instance;}
private:Singleton() = default;~Singleton() = default;
};

使用 CRTP 模板化单例类

CRTP(Curiously Recurring Template Pattern)奇异递归模板模式 是C++中的一个编程技巧,它允许基类使用派生类的类型信息。这种模式在静态多态、计数器等场景中有应用,例如在LLVM项目中被广泛使用。通过CRTP,可以避免虚函数调用的开销,提供更高效和灵活的代码设计。

CRTP的特性表现为:

  • 基类是一个模板类
  • 派生类继承该基类时,将派生类自身作为模板参数传递给基类

实现一个 模板化的单例类,并使用 CRTP来让任意类轻松成为单例,可以这样写:

template<typename T>
class Singleton
{
protected:Singleton() = default;~Singleton() = default;public:Singleton(const Singleton&) = delete;Singleton& operator=(const Singleton&) = delete;Singleton(Singleton&&) = delete;Singleton& operator=(Singleton&&) = delete;static T& GetInstance(){static T instance;return instance;}
};template<typename T> T& g = Singleton<T>::GetInstance();

使用方式

class MyClass : public Singleton<MyClass>
{friend class Singleton<MyClass>; // 保证 GetInstance 可以访问构造函数
private:MyClass() { /* 构造逻辑 */ }
public:void DoSomething() { /* ... */ }
};// 使用
MyClass::GetInstance().DoSomething();
// 或
g<MyClass>.DoSomething();

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

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

相关文章

Eureka 和 Nacos

一、基本介绍EurekaEureka 是 Netflix 公司开发的一款基于 REST 风格的服务注册与发现组件&#xff0c;专为分布式系统设计。它遵循 AP 原则&#xff08;可用性、分区容错性优先&#xff09;&#xff0c;强调在网络分区等异常情况下的服务可用性&#xff0c;是 Spring Cloud Ne…

文件IO笔试题

目录前言一、核心概念&#xff1a;二、关键操作步骤&#xff1a;三、为什么需要文件IO&#xff1f;四、常见类型&#xff1a;五、标准IO源码六、笔试真题和练习1.代码实现1代码实现22.代码实现3.代码实现4.代码实现5.代码实现七、总结前言 文件IO&#xff08;文件输入/输出&am…

前端学习 5:DFT

DFT技术 DFT &#xff08;design for testability&#xff09;&#xff1a;指在设计系统和电路的同时&#xff0c;考虑测试的需求&#xff0c;通过增加一定的硬件开销&#xff0c;获得最大可测性的设计过程。&#xff08;因为增加了硬件&#xff0c;所以也带来了不足&#xff…

最长递增子序列(LIS)问题详解

最长递增子序列LIS问题详解一、问题定义与核心特征1.1 问题描述1.2 核心特征二、基础解法&#xff1a;动态规划&#xff08;DP&#xff09;2.1 解法思路2.2 Java代码实现2.3 复杂度分析三、优化解法&#xff1a;二分查找贪心3.1 核心思路3.2 二分查找的作用3.3 Java代码实现代码…

什么是HTTP长连接、短连接?谁更能抗DoS攻击?

想象你在快餐店点餐&#xff1a; 你&#xff1a;“一个汉堡”收银员&#xff1a;“好的&#xff0c;15元”交易结束&#xff0c;你离开队伍你想加杯可乐&#xff0c;重新排队你&#xff1a;“一杯可乐”收银员&#xff1a;“好的&#xff0c;8元”再次离开… 这种每次沟通后立即…

微软徽标认证是什么?如何快速获取驱动签名?

在Windows系统中安装硬件驱动时&#xff0c;是否遇到过“无法验证发布者”的警告&#xff1f;这正是驱动数字签名在背后发挥作用。对于软件开发者而言&#xff0c;驱动数字签名不仅是系统兼容性的保障&#xff0c;更是企业品牌信任度的核心。一、驱动数字签名的核心作用驱动数字…

Apache Ignite缓存基本操作

这段内容主要讲解了 Apache Ignite 中缓存&#xff08;IgniteCache&#xff09;的基本操作&#xff0c;包括获取缓存、创建缓存、销毁缓存、执行原子操作以及异步操作等。下面我将用中文对这些内容进行详细解释&#xff0c;帮助你更好地理解。一、获取缓存实例&#xff08;Gett…

最新基于R语言结构方程模型分析与实践技术应用

现代统计学理论和方法的不断完善&#xff0c;使科研工作对统计方法的要求也越来越高&#xff0c;面对纷繁复杂的数据&#xff0c;如何选择最为合适的数据分析方法已成为科研工作者&#xff0c;尤其是广大刚处于科研生涯起步阶段的研究生们最为棘手问题。随着科学的发展&#xf…

物联网_TDengine_EMQX_性能测试

一、Tdengine接口开发文档 1、数据库 1.创建数据库 URL /dp/createdb/ method post 请求示例 {"db_name":"demo01" // 必填 }响应示例 // 成功 {"code": 1,"data": {"成功创建数据库": "demo04"},"error…

从分析到优化:Amazon Q CLI 助力 EKS 网络调用链剖析与运维实践

1. 引言 在 Amazon EKS&#xff08;Elastic Kubernetes Service&#xff09;环境中&#xff0c;理解从 ALB&#xff08;Application Load Balancer&#xff09;到 Pod 的完整网络调用链对运维人员至关重要。本文将展示如何利用 Amazon Q CLI 这一 AI 助手工具&#xff0c;通过…

Class10简洁实现

Class10简洁实现 import torch from torch import nn from d2l import torch as d2l# 输入为28*28&#xff0c;输出为10类&#xff0c;第1、2隐藏层256神经元 num_inputs, num_outputs, num_hiddens1, num_hiddens2 784, 10, 256, 256 # 第1个隐藏层丢弃率为0.2&#xff0c;第…

【多线程篇22】:ConcurrentHashMap的并发安全原理剖析

文章目录一、HashMap 的“不安全”&#xff1a;问题的根源1. 数据结构回顾 (JDK 1.8)2. 并发下的致命缺陷&#xff1a;put 操作二、ConcurrentHashMap 的安全之道 (JDK 1.8)1. 核心数据结构2. 安全的 put 操作&#xff1a;分场景精细化加锁3. 安全的 size() 计算&#xff1a;并…

【Java + Vue 实现图片上传后 导出图片及Excel 并压缩为zip压缩包】

系统环境&#xff1a; Java JDK&#xff1a;1.8.0_202 Node.js&#xff1a;v12.2.0 Npm&#xff1a;6.9.0 Java后端实现 Controller /*** xxxx-导出* param response 返回信息体* param files 上传的图片文件* param param1 参数1* param param2 参数2*/PostMapping("/ex…

安科瑞:能源微电网助力工业园区“绿色”发展

朱以真近日&#xff0c;厦门市工业和信息化局印发工业园区绿色智慧微电网建设&#xff0c;拟开展全市工业园区绿色智慧微电网试点通知&#xff0c;那么对于如何实现绿色园区的建设是今天的话题。对工业园区绿色智慧微电网建设需求&#xff0c;其核心价值体现在“源-网-荷-储-充…

VUE2 学习笔记3 v-on、事件修饰符、键盘事件

事件处理v-on用于事件交互。语法&#xff1a;v-on:要绑定的事件“事件触发时执行的函数” &#xff08;函数这里可以写括号&#xff0c;也可以不写&#xff0c;没有影响&#xff09;简写&#xff1a;:事件触发时要执行的函数&#xff0c;在Vue配置参数中&#xff0c;通过method…

变换域通讯系统CCSK的matlab仿真

CCSK&#xff08;Cyclic Code Shift Keying&#xff09;通信系统的MATLAB仿真。实现完整的CCSK调制、AWGN信道传输和解调过程&#xff0c;并计算了误码率&#xff08;BER&#xff09;。 % CCSK通信系统仿真 clear; clc; close all;% 参数设置 L 31; % m序列…

技术演进中的开发沉思-40 MFC系列:多线程协作

今天说说MFC的线程&#xff0c;当年用它实现中间件消息得心应手之时&#xff0c;可以实现一边实时接收数据&#xff0c;一边更新界面图表图文信息&#xff0c;顺滑得让人想吹声口哨。 MFC 多线程它像给程序装上了分身术&#xff0c;让原本只能 “单任务跑腿” 的代码&#xff0…

高速公路自动化安全监测主要内容

近年来&#xff0c;随着社会经济的快速发展&#xff0c;高速公路的通车里程不断增加&#xff0c;交通流量日益增大。与此同时&#xff0c;高速公路交通事故数量也呈现出一定的增长趋势。这些事故不仅造成了大量的人员伤亡和财产损失&#xff0c;还严重影响了社会的稳定和经济的…

完美解决 Ubuntu 中自定义启动器图标重复的问题(以 MATLAB 为例)

如果你在 Ubuntu 上为 MATLAB、PyCharm、Android Studio 或其他第三方应用创建了自定义启动器&#xff0c;并把它固定到了左侧的 Dock 栏&#xff0c;你很可能遇到过这个令人抓狂的场景&#xff1a; 当你满心欢喜地点击固定的图标启动程序后&#xff0c;Dock 栏上竟然“凭空”冒…

一文读懂深度模型优化器,掌握炼丹工具

深度模型优化器是训练神经网络的核心工具&#xff0c;其目标是高效地找到损失函数的最小值。从基础的随机梯度下降&#xff08;SGD&#xff09;到结合一阶动量修正与两阶段更新的Ranger&#xff0c;优化器的发展始终围绕着加速收敛、提升稳定性、适应参数差异和增强泛化能力四大…