0

0

C++怎么实现单例模式_C++设计模式教程【经典】

尼克

尼克

发布时间:2026-03-04 08:50:31

|

859人浏览过

|

来源于php中文网

原创

最稳妥的线程安全单例方案是c++11起使用局部静态变量初始化,编译器自动保证只执行一次且线程安全;需禁用所有构造与赋值操作(含移动),并注意构造函数不可抛异常。

c++怎么实现单例模式_c++设计模式教程【经典】

单例的线程安全怎么保证

多线程环境下直接用懒汉式(首次调用时初始化)会出问题:两个线程同时判断 instance == nullptr,都进到 new 分支,构造两次,析构时崩溃或内存泄漏。

最稳妥的做法是用 C++11 起支持的局部静态变量初始化,编译器自动加锁且只执行一次:

class Singleton {
public:
    static Singleton& getInstance() {
        static Singleton instance; // ✅ 线程安全,无需手动同步
        return instance;
    }
private:
    Singleton() = default;
    ~Singleton() = default;
    Singleton(const Singleton&) = delete;
    Singleton& operator=(const Singleton&) = delete;
};
  • 别手写 std::mutex + double-checked locking:容易漏锁、内存重排,C++11 前才考虑它
  • 别用 std::call_once + std::once_flag:可行但冗余,不如局部静态简洁
  • 注意:这个方案要求构造函数不能抛异常,否则第二次调用会直接 abort

为什么不能用全局对象替代单例

全局对象在 main() 之前初始化,但它的初始化顺序跨编译单元是未定义的。如果 A.cpp 的全局对象依赖 B.cpp 的单例,而 B 的单例还没构造,就会访问野指针。

局部静态变量则不同:它的初始化发生在第一次调用函数时,时机可控,依赖关系明确。

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

ChatGPT Writer
ChatGPT Writer

免费 Chrome 扩展程序,使用 ChatGPT AI 生成电子邮件和消息。

下载
  • 全局对象还可能被链接器优化掉(尤其没显式引用时),导致运行时报 undefined reference
  • 单例可延迟初始化,节省启动时间;全局对象不管用不用,一加载就构造
  • 单例能控制析构顺序(比如在 main 结束后、全局对象析构前清理资源),全局对象做不到

delete 构造函数和赋值操作符要写全

只禁用拷贝构造、不删移动构造,C++11 后仍可能被移动构造出新对象,破坏唯一性。

必须显式删除所有可能绕过单例控制的入口:

private:
    Singleton() = default;
    ~Singleton() = default;
    Singleton(const Singleton&) = delete;
    Singleton& operator=(const Singleton&) = delete;
    Singleton(Singleton&&) = delete;
    Singleton& operator=(Singleton&&) = delete;
  • 漏删移动语义是常见疏忽,尤其在类有资源管理逻辑时
  • 构造函数设为 private 但没删拷贝/移动,编译器会自动生成默认版本,等于没封住
  • 如果真需要“可移动的单例”,说明设计本身有问题——单例的本质就是全局唯一,不该被转移

单例生命周期比 main 长怎么办

局部静态变量的析构发生在 main 返回后、全局对象析构期间,顺序不可控。如果单例里持有日志句柄、网络连接等资源,可能在依赖它的其他全局对象析构时已失效。

更可控的方式是用裸指针 + 显式销毁,把控制权交还给使用者:

class Singleton {
public:
    static Singleton* getInstance() {
        if (!instance) {
            instance = new Singleton();
        }
        return instance;
    }
    static void destroy() {
        delete instance;
        instance = nullptr;
    }
private:
    static Singleton* instance;
};
  • 这种模式叫“manual lifetime management”,适合嵌入式或游戏引擎等对析构顺序敏感的场景
  • 必须确保 destroy() 在所有依赖它的对象析构前调用,通常放在 main 末尾或 atexit 回调里
  • 别忘了加 thread_local 或锁保护 instance 指针读写,否则多线程下仍不安全

真正难的从来不是写出来,而是想清楚:这个“唯一实例”到底该活多久、谁来决定它什么时候死、以及有没有人会在它死后还试图访问它。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

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

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

294

2025.08.29

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

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

105

2025.10.23

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

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

294

2025.08.29

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

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

105

2025.10.23

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

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

723

2023.08.10

Python 多线程与异步编程实战
Python 多线程与异步编程实战

本专题系统讲解 Python 多线程与异步编程的核心概念与实战技巧,包括 threading 模块基础、线程同步机制、GIL 原理、asyncio 异步任务管理、协程与事件循环、任务调度与异常处理。通过实战示例,帮助学习者掌握 如何构建高性能、多任务并发的 Python 应用。

372

2025.12.24

java多线程相关教程合集
java多线程相关教程合集

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

27

2026.01.21

C++多线程相关合集
C++多线程相关合集

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

27

2026.01.21

Swift iOS架构设计与MVVM模式实战
Swift iOS架构设计与MVVM模式实战

本专题聚焦 Swift 在 iOS 应用架构设计中的实践,系统讲解 MVVM 模式的核心思想、数据绑定机制、模块拆分策略以及组件化开发方法。内容涵盖网络层封装、状态管理、依赖注入与性能优化技巧。通过完整项目案例,帮助开发者构建结构清晰、可维护性强的 iOS 应用架构体系。

3

2026.03.03

热门下载

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

精品课程

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

共94课时 | 10.6万人学习

C 教程
C 教程

共75课时 | 5.1万人学习

C++教程
C++教程

共115课时 | 20.3万人学习

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

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