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

相关推荐
ChiaWei Lee几秒前
【C++初学】C++核心编程技术详解(二):类与继承
c++
2401_890665861 分钟前
免费送源码:Java+SpringBoot+MySQL SpringBoot网上宠物领养管理系统 计算机毕业设计原创定制
java·vue.js·spring boot·python·mysql·pycharm·html5
湫qiu23 分钟前
为什么我建议你主动释放直接内存 - Java
java·linux·后端
9号达人27 分钟前
Java 11 新特性详解与实践
java·后端·面试
异常君28 分钟前
Java 中滥用 Optional 导致的意外问题与正确使用建议
java
异常君28 分钟前
Java 项目中对异常链(Exception Chaining)的误用与正确操作
java
疯狂学习GIS29 分钟前
本地安装JAR包出现The goal you specified requires a project to execute的处理
java·后端·maven
异常君29 分钟前
Java 动态代理全解析:JDK 代理 VS CGLIB 代理
java
Jtti1 小时前
Debian环境下Java应用无法启动的原因有哪些
java·python·debian
上线之叁1 小时前
小迪安全-tp框架反序列化,利用链,rce执行,文件删除
java·开发语言