0

0

如何在C++中实现单例模式_C++单例模式设计与实现

下次还敢

下次还敢

发布时间:2025-09-22 19:15:01

|

692人浏览过

|

来源于php中文网

原创

单例模式通过私有构造函数、静态实例和全局访问点确保类唯一实例,常用饿汉式(类加载时创建)和懒汉式(首次使用时创建)。懒汉式需处理线程安全,推荐C++11的std::call_once实现双重初始化保护。为防止实例被破坏,需禁用拷贝构造和赋值操作。生命周期管理可借助静态局部变量,其析构在程序末尾自动进行,避免资源释放顺序问题。多线程测试可通过并发调用getInstance()验证是否返回同一地址,确认线程安全。

如何在c++中实现单例模式_c++单例模式设计与实现

单例模式的核心在于确保一个类只有一个实例,并提供一个全局访问点。这在很多场景下非常有用,比如管理配置、数据库连接等等。但实现起来也有些坑,需要注意线程安全和生命周期管理。

解决方案

最常见的实现方式是懒汉式和饿汉式。

  • 饿汉式: 在类加载的时候就创建实例,简单粗暴,但可能会浪费资源。

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

    class Singleton {
    private:
        Singleton() {} // 私有构造函数
        static Singleton instance; // 静态成员变量,类加载时初始化
    
    public:
        static Singleton& getInstance() {
            return instance;
        }
    };
    
    Singleton Singleton::instance; // 静态成员变量初始化
  • 懒汉式: 在第一次使用的时候才创建实例,延迟加载,但需要考虑线程安全。

    class Singleton {
    private:
        Singleton() {}
        static Singleton* instance;
        static std::mutex mutex; // 互斥锁
    
    public:
        static Singleton* getInstance() {
            if (instance == nullptr) {
                std::lock_guard lock(mutex); // 加锁
                if (instance == nullptr) { // Double-Check Locking
                    instance = new Singleton();
                }
            }
            return instance;
        }
    };
    
    Singleton* Singleton::instance = nullptr;
    std::mutex Singleton::mutex;

懒汉式中使用了双重检查锁(Double-Check Locking),看似解决了线程安全问题,但实际上在某些编译器和CPU架构下可能会失效。所以,更推荐使用C++11提供的

std::call_once
来保证线程安全。

#include 
#include 

class Singleton {
private:
    Singleton() { std::cout << "Singleton instance created." << std::endl; }
    ~Singleton() { std::cout << "Singleton instance destroyed." << std::endl; }
    static Singleton* instance;
    static std::once_flag onceFlag;

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

    static Singleton* getInstance() {
        std::call_once(onceFlag, []() {
            instance = new Singleton();
        });
        return instance;
    }

    void doSomething() {
        std::cout << "Singleton is doing something!" << std::endl;
    }

    static void destroyInstance() {
        delete instance;
        instance = nullptr;
    }
};

Singleton* Singleton::instance = nullptr;
std::once_flag Singleton::onceFlag;

int main() {
    Singleton* instance1 = Singleton::getInstance();
    instance1->doSomething();

    Singleton* instance2 = Singleton::getInstance();
    instance2->doSomething();

    if (instance1 == instance2) {
        std::cout << "Both instances are the same." << std::endl;
    }

    Singleton::destroyInstance(); // 手动释放单例对象
    return 0;
}

这种方式利用

std::call_once
保证
instance
只会被初始化一次,避免了多线程竞争的问题。

奥硕企业网站管理系统3.0.2
奥硕企业网站管理系统3.0.2

临沂奥硕软件有限公司拥有国内一流的企业网站管理系统,奥硕企业网站管理系统真正会打字就会建站的管理系统,其强大的扩展性可以满足企业网站实现各种功能(唯一集成3O多套模版的企业建站系统)奥硕企业网站管理系统具有一下特色功能1、双语双模(中英文采用单独模板设计,可制作中英文不同样式的网站)2、在线编辑JS动态菜单支持下拉效果,同时生成中文,英文,静态3个JS菜单3、在线制作并调用FLASH展示动画4、自

下载

如何避免单例模式被破坏?

单例模式很容易被破坏,比如通过拷贝构造函数、赋值运算符或者反射等方式创建多个实例。因此,需要禁用拷贝构造函数和赋值运算符,并将构造函数设置为私有。

class Singleton {
private:
    Singleton() {}
    Singleton(const Singleton&); // 禁用拷贝构造函数
    Singleton& operator=(const Singleton&); // 禁用赋值运算符
    static Singleton* instance;
    static std::once_flag onceFlag;

public:
    static Singleton* getInstance() {
        std::call_once(onceFlag, []() {
            instance = new Singleton();
        });
        return instance;
    }
};

Singleton* Singleton::instance = nullptr;
std::once_flag Singleton::onceFlag;

单例模式的生命周期管理问题?

单例对象的生命周期是一个需要特别注意的问题。在程序结束时,如果单例对象依赖于其他对象,而这些对象已经被销毁,那么单例对象的析构函数可能会导致程序崩溃。

一种简单的解决方案是使用静态局部变量来实现单例,利用C++的静态变量的生命周期管理机制。

class Singleton {
private:
    Singleton() {}
    ~Singleton(){}
public:
    Singleton(const Singleton&) = delete;
    Singleton& operator=(const Singleton&) = delete;

    static Singleton& getInstance() {
        static Singleton instance; // 静态局部变量
        return instance;
    }
};

这种方式可以保证在程序结束时,单例对象会在其他静态对象销毁之后再销毁。当然,这只是一种简化方案,更复杂的场景可能需要更精细的生命周期管理。

如何在多线程环境下测试单例模式的线程安全性?

要测试单例模式的线程安全性,可以使用多线程并发访问单例对象,并检查是否出现多个实例或者数据竞争的情况。

#include 
#include 
#include 
#include 
#include 

// 使用call_once实现的单例模式 (代码见前面的例子)

void threadFunc(int threadId) {
    Singleton* instance = Singleton::getInstance();
    std::cout << "Thread " << threadId << ": Singleton instance address = " << instance << std::endl;
    instance->doSomething();
    std::this_thread::sleep_for(std::chrono::milliseconds(100)); // 模拟一些工作
}

int main() {
    std::vector threads;
    int numThreads = 10;

    for (int i = 0; i < numThreads; ++i) {
        threads.emplace_back(threadFunc, i);
    }

    for (auto& thread : threads) {
        thread.join();
    }

    Singleton::destroyInstance();
    return 0;
}

运行这个程序,如果所有线程都输出了相同的单例对象地址,并且没有出现异常,那么说明单例模式的线程安全性得到了保证。

相关专题

更多
java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

1468

2023.10.24

Go语言中的运算符有哪些
Go语言中的运算符有哪些

Go语言中的运算符有:1、加法运算符;2、减法运算符;3、乘法运算符;4、除法运算符;5、取余运算符;6、比较运算符;7、位运算符;8、按位与运算符;9、按位或运算符;10、按位异或运算符等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

229

2024.02.23

php三元运算符用法
php三元运算符用法

本专题整合了php三元运算符相关教程,阅读专题下面的文章了解更多详细内容。

85

2025.10.17

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

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

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

482

2023.08.10

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

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

143

2025.12.24

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

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

3

2026.01.21

Java编译相关教程合集
Java编译相关教程合集

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

9

2026.01.21

热门下载

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

精品课程

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

共94课时 | 7.2万人学习

C 教程
C 教程

共75课时 | 4.1万人学习

C++教程
C++教程

共115课时 | 13.1万人学习

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

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