C++ 单例模式超详细讲解

C++ 单例模式超详细讲解

C++ 单例模式(Singleton)超详细讲解

我会用最通俗、最完整 的方式,把单例模式的背景、意义、用法、优势、实现、坑点一次性讲透,新手也能完全看懂。

一、什么是单例模式?

单例模式 = 一个类,在整个程序运行期间,只能创建唯一一个对象,不能创建第二个。

简单说:

  • 这个类永远只有一个实例

  • 无论你在代码哪里用,拿到的都是同一个对象

  • 禁止外部手动 new、禁止拷贝、禁止赋值

二、背景:为什么会出现单例模式?

在程序里,有些对象天生就应该只有一个,如果允许多个实例,会出大问题:

常见场景:

  • 日志管理器(多个日志对象会导致日志混乱、重复写入)

  • 配置管理器(全局配置只应该读一份)

  • 数据库连接池(重复创建连接浪费资源)

  • 线程池、缓存管理器、打印机管理器、游戏引擎管理器

  • 全局工具类(只需要一份,不需要反复创建)

如果不控制实例数量:

  • 资源浪费

  • 数据不一致

  • 逻辑错误

  • 程序崩溃

于是单例模式 就诞生了,专门解决:
全局唯一实例 + 统一访问点

三、单例模式的核心意义

一句话总结:
保证一个类在程序生命周期内有且仅有一个实例,并提供一个全局访问点。

它解决两个核心问题:

  1. 全局唯一:避免重复创建、资源冲突

  2. 全局可访问:不用到处传递对象,随时能获取

四、单例模式的优势(为什么要用?)

1. 严格控制唯一实例

从语法层面禁止创建多个对象,从根源避免错误。

2. 节约系统资源

像数据库连接、日志、配置文件,只初始化一次,不重复消耗。

3. 全局统一访问

任何地方直接获取实例,不用层层传参,代码更简洁。

4. 延迟初始化(懒汉模式)

用到时才创建,不浪费启动时间。

5. 避免全局变量的缺点

全局变量:

  • 没有封装

  • 可以被随意修改

  • 没有控制构造 / 析构

单例:

  • 完全封装

  • 可控生命周期

  • 线程安全可控制

  • 更优雅、更安全

五、单例模式的 4 个关键规则(必须记住)

要写一个正确的 C++ 单例,必须满足:

  1. 构造函数私有化 :禁止外部 new

  2. 删除拷贝构造 + 赋值运算符:禁止拷贝、赋值

  3. 提供一个静态获取实例函数getInstance\(\)

  4. 唯一实例存储在静态成员变量

六、C++ 单例的两种经典实现

1. 饿汉模式(Eager)

程序一启动就创建实例

  • 优点:简单、天生线程安全

  • 缺点:启动稍慢

cpp 复制代码
class Singleton {
public:
    // 禁用拷贝和赋值
    Singleton(const Singleton&) = delete;
    Singleton& operator=(const Singleton&) = delete;

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

    // 测试函数
    void doSomething() {
        // ...
    }

private:
    // 构造函数私有化
    Singleton() {}

    // 程序启动时就创建唯一实例
    static Singleton instance;
};

// 静态成员初始化
Singleton Singleton::instance;

使用方式:

cpp 复制代码
Singleton& obj = Singleton::getInstance();
obj.doSomething();

2. 懒汉模式(Lazy)------ 最常用

用到时才创建实例(延迟初始化)

C++11 之后最推荐、最简单、线程安全的写法:

cpp 复制代码
class Singleton {
public:
    Singleton(const Singleton&) = delete;
    Singleton& operator=(const Singleton&) = delete;

    static Singleton& getInstance() {
        // C++11 保证 static 内部变量线程安全
        static Singleton instance;
        return instance;
    }

    void doSomething() {}

private:
    Singleton() {}
};

这是现代 C++ 最优单例实现

  • 线程安全

  • 延迟加载

  • 自动销毁

  • 代码极简

七、单例模式怎么用?

cpp 复制代码
// 获取单例对象
auto& logger = Singleton::getInstance();

// 使用成员函数
logger.doSomething();

// 永远是同一个对象
auto& logger2 = Singleton::getInstance();
// logger 和 logger2 是同一个实例

八、单例模式的缺点

没有任何设计模式完美,单例也有坑:

  1. 过度使用会造成代码耦合

  2. 难以单元测试(因为全局唯一,无法 mock)

  3. 多线程下要注意线程安全

  4. 生命周期不好控制(程序结束才销毁)

  5. 隐藏依赖关系(代码看不到参数传递)

结论:单例很好,但不要滥用。

九、单例模式适用场景

你可以放心用单例的情况:

  • 日志系统

  • 配置管理

  • 数据库连接池

  • 缓存

  • 线程池

  • 全局管理器(引擎、UI、音频等)


总结(超精简版)

  1. 单例 = 一个类只能有一个对象

  2. 目的:全局唯一、节约资源、统一访问

  3. 核心规则:私有构造 + 禁用拷贝 + 静态访问点

  4. 最佳实现:C++11 静态局部变量(懒汉、线程安全)

  5. 优势:安全、简洁、无资源浪费

  6. 缺点:不能滥用,会造成耦合

(注:文档部分内容可能由 AI 生成)

相关推荐
之歆5 小时前
Day17_JavaScript高级核心垃圾回收执行上下文闭包完全指南(上)
开发语言·javascript·ecmascript
Emerson_20265 小时前
stack,queue,list的区别和联系
数据结构·c++·list·queue·stack
weixin_550083155 小时前
基于Python的豆瓣电影数据爬取与可视化分析
开发语言·python
xyq20245 小时前
jQuery Mobile Data 属性详解
开发语言
王老师青少年编程5 小时前
2026年全国青少年信息素养大赛初赛真题(算法应用主题赛C++初中组初赛真题2:文末附答案和解析)
c++·真题·答案·初赛·2026年·初中组·青少年信息素养大
YOLO数据集集合5 小时前
光伏板缺陷检测数据集|红外可见光双模态|无人机光伏巡检|智慧电网光伏识别数据集
开发语言·yolo·目标检测·无人机
AI人工智能+电脑小能手5 小时前
【大白话说Java面试题 第74题】【Mysql篇】第4题:InnoDB 和 MyISAM 的数据文件存储区别?
java·开发语言·mysql·面试
qq_2518364575 小时前
基于java Web快乐岛儿童网站设计与实现
java·开发语言·前端
码界筑梦坊5 小时前
147-基于Python的IT行业招聘数据可视化分析系统
开发语言·python·信息可视化·数据分析·django·毕业设计