0

0

c++中如何实现单例模式_c++单例模式的代码实现步骤【指南】

冰火之心

冰火之心

发布时间:2026-01-20 15:39:30

|

386人浏览过

|

来源于php中文网

原创

单例不能用全局变量代替,因其不满足延迟初始化、全局唯一和线程安全三要素;C++11起推荐用local static实现,简洁且线程安全。

c++中如何实现单例模式_c++单例模式的代码实现步骤【指南】

为什么不能用全局变量代替单例

全局变量在多线程环境下不安全,且无法控制初始化时机——static局部变量在 C++11 起才保证线程安全的首次初始化,而全局对象的构造顺序跨编译单元不可控,容易引发 undefined behavior。单例的核心诉求是「延迟初始化 + 全局唯一 + 线程安全」,这三点全局变量一个都做不到。

最简安全写法:C++11 以后推荐用 local static

利用函数内 static 变量的“首次调用时初始化”和“C++11 标准保证的线程安全”特性,代码极简且无锁

class Singleton {
public:
    static Singleton& getInstance() {
        static Singleton instance; // ✅ 线程安全,仅首次调用构造
        return instance;
    }

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

private:
    Singleton() = default; // 可加日志或资源初始化
};

注意点:

  • getInstance() 必须返回引用(Singleton&),返回值会触发拷贝,破坏单例语义
  • 构造函数设为 private,防止外部 new 或直接实例化
  • 显式删除拷贝构造与赋值操作符,避免误用
  • 不要在构造函数里调用其他单例的 getInstance(),可能触发静态初始化顺序问题

需要手动管理生命周期?慎用 std::unique_ptr + new

只有在必须延迟析构(比如依赖其他单例销毁后才释放)或需定制销毁逻辑时,才考虑堆分配。但代价是引入显式内存管理风险:

立即学习C++免费学习笔记(深入)”;

Playground AI
Playground AI

AI图片生成和修图

下载
class Singleton {
public:
    static Singleton& getInstance() {
        static std::unique_ptr instance;
        if (!instance) {
            instance = std::make_unique();
        }
        return *instance;
    }

private:
    Singleton() = default;
    ~Singleton() = default; // 可加清理逻辑
};

隐患:

  • 如果程序异常退出(如 std::abort()),~Singleton() 可能不被调用
  • 多个单例之间若存在析构依赖,仍可能 crash(C++ 不保证静态对象析构顺序)
  • 比 local static 写法多一次指针解引用,性能略低(通常可忽略)

双检锁(DCLP)在 C++ 中已过时且极易出错

早期为兼容 C++03 手写双重检查锁定(Double-Checked Locking Pattern),现在完全没必要。它要求:

  • std::atomic 存储指针(裸指针 + volatile 在 C++11 后无效)
  • 两次 load() 都需指定内存序(如 memory_order_acquire
  • 中间 new 操作必须确保构造完成后再发布指针,否则其他线程可能看到未初始化对象

哪怕抄对了,也比 local static 多出锁开销和复杂度。C++11 标准明确支持 local static 的线程安全初始化,这是标准给出的正解。

真正要注意的是:单例不是银弹。它的全局状态、隐式依赖和测试困难性,在大型项目中往往比实现本身更伤人。

相关专题

更多
全局变量怎么定义
全局变量怎么定义

本专题整合了全局变量相关内容,阅读专题下面的文章了解更多详细内容。

78

2025.09.18

python 全局变量
python 全局变量

本专题整合了python中全局变量定义相关教程,阅读专题下面的文章了解更多详细内容。

96

2025.09.18

c++怎么把double转成int
c++怎么把double转成int

本专题整合了 c++ double相关教程,阅读专题下面的文章了解更多详细内容。

53

2025.08.29

C++中int、float和double的区别
C++中int、float和double的区别

本专题整合了c++中int和double的区别,阅读专题下面的文章了解更多详细内容。

99

2025.10.23

c++中volatile关键字的作用
c++中volatile关键字的作用

本专题整合了c++中volatile关键字的相关内容,阅读专题下面的文章了解更多详细内容。

69

2025.10.23

堆和栈的区别
堆和栈的区别

堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

392

2023.07.18

堆和栈区别
堆和栈区别

堆(Heap)和栈(Stack)是计算机中两种常见的内存分配机制。它们在内存管理的方式、分配方式以及使用场景上有很大的区别。本文将详细介绍堆和栈的特点、区别以及各自的使用场景。php中文网给大家带来了相关的教程以及文章欢迎大家前来学习阅读。

572

2023.08.10

线程和进程的区别
线程和进程的区别

线程和进程的区别:线程是进程的一部分,用于实现并发和并行操作,而线程共享进程的资源,通信更方便快捷,切换开销较小。本专题为大家提供线程和进程区别相关的各种文章、以及下载和课程。

481

2023.08.10

Java JVM 原理与性能调优实战
Java JVM 原理与性能调优实战

本专题系统讲解 Java 虚拟机(JVM)的核心工作原理与性能调优方法,包括 JVM 内存结构、对象创建与回收流程、垃圾回收器(Serial、CMS、G1、ZGC)对比分析、常见内存泄漏与性能瓶颈排查,以及 JVM 参数调优与监控工具(jstat、jmap、jvisualvm)的实战使用。通过真实案例,帮助学习者掌握 Java 应用在生产环境中的性能分析与优化能力。

19

2026.01.20

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
C# 教程
C# 教程

共94课时 | 7.1万人学习

C 教程
C 教程

共75课时 | 4.1万人学习

C++教程
C++教程

共115课时 | 13万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号