单例模式(Singleton Pattern)

C++ 单例模式

单例模式(Singleton Pattern)

一、核心定义

单例模式是创建型设计模式 ,确保一个类有且只有一个实例,并提供一个全局访问点获取该实例。

二、核心特点

  1. 一个类只能创建唯一对象
  2. 自行创建实例
  3. 向整个系统提供这个实例
  4. 无参构造函数私有化
  5. 禁止拷贝、禁止赋值

三、使用场景

  • 日志管理器
  • 配置文件读取
  • 数据库连接池
  • 线程池、缓存、打印机池
  • 全局唯一的工具类

四、C++ 单例模式 5 种标准实现(可直接编译)

实现 1:饿汉式(最简单、线程安全)

程序启动时就创建实例,天生线程安全,无多线程问题。

cpp 复制代码
#include <iostream>
using namespace std;

class Singleton
{
public:
    // 全局访问点
    static Singleton& getInstance()
    {
        return instance;
    }

    void show()
    {
        cout << "饿汉式单例" << endl;
    }

    // 禁止拷贝、禁止赋值
    Singleton(const Singleton&) = delete;
    Singleton& operator=(const Singleton&) = delete;

private:
    // 构造私有
    Singleton() {}
    // 程序启动就初始化
    static Singleton instance;
};

// 静态变量初始化
Singleton Singleton::instance;

int main()
{
    Singleton& s1 = Singleton::getInstance();
    Singleton& s2 = Singleton::getInstance();

    cout << &s1 << endl;
    cout << &s2 << endl; // 地址相同

    return 0;
}

优点 :简单、线程安全
缺点:不用也会创建,可能浪费资源


实现 2:懒汉式(基础版,非线程安全)

第一次使用时才创建实例。

cpp 复制代码
#include <iostream>
using namespace std;

class Singleton
{
public:
    static Singleton* getInstance()
    {
        if (instance == nullptr)
        {
            instance = new Singleton();
        }
        return instance;
    }

    void show() { cout << "懒汉式单例" << endl; }

    Singleton(const Singleton&) = delete;
    Singleton& operator=(const Singleton&) = delete;

private:
    Singleton() {}
    static Singleton* instance;
};

Singleton* Singleton::instance = nullptr;

int main()
{
    Singleton* s1 = Singleton::getInstance();
    Singleton* s2 = Singleton::getInstance();
    return 0;
}

注意 :多线程不安全,高并发会创建多个实例


实现 3:线程安全懒汉式(加锁)

C++11 线程安全版本

cpp 复制代码
#include <iostream>
#include <mutex>
using namespace std;

mutex mtx;

class Singleton
{
public:
    static Singleton* getInstance()
    {
        lock_guard<mutex> lock(mtx);
        if (instance == nullptr)
        {
            instance = new Singleton();
        }
        return instance;
    }

    Singleton(const Singleton&) = delete;
    Singleton& operator=(const Singleton&) = delete;

private:
    Singleton() {}
    static Singleton* instance;
};

Singleton* Singleton::instance = nullptr;

实现 4:双检查锁 DCL(高性能线程安全)

企业最常用

cpp 复制代码
#include <iostream>
#include <mutex>
using namespace std;

class Singleton
{
public:
    static Singleton* getInstance()
    {
        if (instance == nullptr)
        {
            lock_guard<mutex> lock(mtx);
            if (instance == nullptr)
            {
                instance = new Singleton();
            }
        }
        return instance;
    }

    Singleton(const Singleton&) = delete;
    Singleton& operator=(const Singleton&) = delete;

private:
    Singleton() {}
    static Singleton* instance;
    static mutex mtx;
};

Singleton* Singleton::instance = nullptr;
mutex Singleton::mtx;

实现 5:C++11 最优方案 Meyers 单例(推荐!)

最简单、线程安全、无内存泄漏

cpp 复制代码
#include <iostream>
using namespace std;

class Singleton
{
public:
    static Singleton& getInstance()
    {
        static Singleton instance;
        return instance;
    }

    void show() { cout << "Meyers 单例(C++11最佳)" << endl; }

    Singleton(const Singleton&) = delete;
    Singleton& operator=(const Singleton&) = delete;

private:
    Singleton() {}
};

int main()
{
    Singleton& s1 = Singleton::getInstance();
    Singleton& s2 = Singleton::getInstance();
    s1.show();
    return 0;
}

优点:

  • 线程安全(C++11 保证静态变量初始化原子性)
  • 懒加载
  • 无内存泄漏
  • 代码极简

五、单例模式自动释放(析构安全)

加入内部回收类,程序结束自动释放单例

cpp 复制代码
#include <iostream>
using namespace std;

class Singleton
{
public:
    static Singleton* getInstance()
    {
        if (instance == nullptr)
        {
            instance = new Singleton();
        }
        return instance;
    }

    class AutoDelete
    {
    public:
        ~AutoDelete()
        {
            if (Singleton::instance)
            {
                delete Singleton::instance;
                cout << "单例已自动释放" << endl;
            }
        }
    };

private:
    Singleton() {}
    static Singleton* instance;
    static AutoDelete ad;
};

Singleton* Singleton::instance = nullptr;
Singleton::AutoDelete Singleton::ad;

六、五种单例对比总结

实现方式 线程安全 性能 推荐指数
饿汉式 安全 高 ⭐⭐⭐
基础懒汉式 不安全 高 不推荐
加锁懒汉式 安全 低 ⭐⭐
双检查锁 DCL 安全 高 ⭐⭐⭐⭐
Meyers 单例 安全 极高 ⭐⭐⭐⭐⭐

七、C++ 单例必须遵守的 4 条规则

  1. 构造函数私有化
  2. 禁用拷贝构造
  3. 禁用赋值重载
  4. 提供全局唯一访问点

八、企业最佳实践

  1. 优先使用 Meyers 单例(C++11 最优)
  2. 禁止手动 new/delete,使用智能指针或自动释放
  3. 多线程环境必须使用线程安全版本
  4. 单例不建议存放大量数据,避免内存飙升
相关推荐
大风起兮云飞扬丶1 小时前
Java——枚举
java·开发语言
小灰灰搞电子1 小时前
Rust+Slint 实现高级动态消息提示框源码分享
开发语言·rust
Dev _1 小时前
Python解释器安装在系统级目录导致命令行用户‌没有权限‌向该目录写入文件
开发语言·python
牵猫散步的鱼儿2 小时前
C++ 内存分区
c++
qq_406981032 小时前
大白话rust系列08 当变量遮蔽遇上引用,探究变量遮蔽的本质
开发语言·后端·rust
choumin2 小时前
C++ 标准容器为什么不能存引用
c++·容器·引用类型
喵了几个咪2 小时前
GoWind ShortPlay 拆解:不用模型的推荐闭环——埋点回流、三路召回与已看去重
开发语言·后端·微服务·golang·gowind
谙弆悕博士2 小时前
用 C 写了个 Windows 聊天室,踩了几个多线程和控制台的坑
c语言·开发语言·c++·windows·网络编程·聊天室
Canmag 兴隆磁性2 小时前
回复磁导率 μ_R:永磁体在动态磁路中的关键参数
开发语言·学习·r语言·永磁材料·充磁·磁导率
CRMEB系统商城2 小时前
鲜花零售的预售与积分营销
开发语言·人工智能·科技·小程序·零售