C++单例模式

定义

  1. 类的实例只有一个

特点

  1. 构造函数私有化,在类内部只调用一次
  2. 拷贝构造函数私有化或者禁用

饿汉单例

  1. 类加载的时候立刻进行实例化
    1. 定义这个单例类的时候,就把这个静态的单例对象创建出来了

example

cpp 复制代码
// 饿汉模式
class TaskQueue
{
public:
    // = delete 代表函数禁用, 也可以将其访问权限设置为私有
    TaskQueue(const TaskQueue& obj) = delete;
    TaskQueue& operator=(const TaskQueue& obj) = delete;
    static TaskQueue* getInstance()
    {
        return m_taskQ;
    }
private:
    TaskQueue() = default;
    static TaskQueue* m_taskQ;
};
// 静态成员初始化放到类外部处理
TaskQueue* TaskQueue::m_taskQ = new TaskQueue;

int main()
{
    TaskQueue* obj = TaskQueue::getInstance();
}

懒汉单例

  1. 类加载的时候不去创建这个唯一的实例,而是在需要使用的时候再进行实例化

example

cpp 复制代码
// 懒汉模式
class TaskQueue
{
public:
    // = delete 代表函数禁用, 也可以将其访问权限设置为私有
    TaskQueue(const TaskQueue& obj) = delete;
    TaskQueue& operator=(const TaskQueue& obj) = delete;
    static TaskQueue* getInstance()
    {
        if(m_taskQ == nullptr)
        {
            m_taskQ = new TaskQueue;
        }
        return m_taskQ;
    }
private:
    TaskQueue() = default;
    static TaskQueue* m_taskQ;
};
TaskQueue* TaskQueue::m_taskQ = nullptr;

缺点

  1. 多线程环境下,可能生成多个单例
    1. 在调用getInstance()函数获取单例对象的时候,如果在单线程情况下是没有什么问题的,如果是多个线程,调用这个函数去访问单例对象就有问题了。假设有三个线程同时执行了getInstance()函数,在这个函数内部每个线程都会new出一个实例对象。此时,这个任务队列类的实例对象不是一个而是3个,很显然这与单例模式的定义是相悖的

解决方案

  1. 加锁
  2. 局部静态变量
cpp 复制代码
class TaskQueue
{
public:
    // = delete 代表函数禁用, 也可以将其访问权限设置为私有
    TaskQueue(const TaskQueue& obj) = delete;
    TaskQueue& operator=(const TaskQueue& obj) = delete;
    static TaskQueue* getInstance()
    {
        static TaskQueue taskQ;
        return &taskQ;
    }
    void print()
    {
        cout << "hello, world!!!" << endl;
    }

private:
    TaskQueue() = default;
};

int main()
{
    TaskQueue* queue = TaskQueue::getInstance();
    queue->print();
    return 0;
}

在程序的第 9、10 行定义了一个静态局部队列对象,并且将这个对象作为了唯一的单例实例。使用这种方式之所以是线程安全的,是因为在C++11标准中有如下规定,并且这个操作是在编译时由编译器保证的:

如果指令逻辑进入一个未被初始化的声明变量,所有并发执行应当等待该变量完成初始化。

PS:局部静态变量

  1. 在函数内部进行初始化,且只在第一次进入函数时执行初始化操作。初始化方式和普通局部变量类似,只是因为它是静态的,后续函数调用时不会再次初始化。

example

相关推荐
野生的码农3 小时前
码农的妇产科实习记录
android·java·人工智能
会周易的程序员3 小时前
多模态AI 基于工业级编译技术的PLC数据结构解析与映射工具
数据结构·c++·人工智能·单例模式·信息可视化·架构
毕设源码-赖学姐4 小时前
【开题答辩全过程】以 高校人才培养方案管理系统的设计与实现为例,包含答辩的问题和答案
java
一起努力啊~4 小时前
算法刷题-二分查找
java·数据结构·算法
小途软件4 小时前
高校宿舍访客预约管理平台开发
java·人工智能·pytorch·python·深度学习·语言模型
J_liaty4 小时前
Java版本演进:从JDK 8到JDK 21的特性革命与对比分析
java·开发语言·jdk
+VX:Fegn08954 小时前
计算机毕业设计|基于springboot + vue律师咨询系统(源码+数据库+文档)
java·数据库·vue.js·spring boot·后端·课程设计
daidaidaiyu4 小时前
一文学习和实践 当下互联网安全的基石 - TLS 和 SSL
java·netty
hssfscv5 小时前
Javaweb学习笔记——后端实战2_部门管理
java·笔记·学习
NE_STOP5 小时前
认识shiro
java