首页 > 后端开发 > C++ > 正文

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

下次还敢
发布: 2025-09-22 19:15:01
原创
682人浏览过
单例模式通过私有构造函数、静态实例和全局访问点确保类唯一实例,常用饿汉式(类加载时创建)和懒汉式(首次使用时创建)。懒汉式需处理线程安全,推荐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<std::mutex> 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 <mutex>
#include <iostream>

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
登录后复制
只会被初始化一次,避免了多线程竞争的问题。

创意艺术设计的网站模板
创意艺术设计的网站模板

创意艺术设计的网站模板 创意艺术是指是把再简单不过的东西或想法不断延伸给予的另一种表现方式,创意设计包括工业设计、建筑设计、包装设计、平面设计、服装设计、个人创意特区等内容。 设计除了具备“初级设计”和“次设计”的因素外,还需要融入“与众不同的设计理念——创意”。搜索 一、初级设计 范围划分一般是以是否在表达图形上是否以“具象化”为指导目标,标志设计就像绘画一样真实表现图形。 二、次级设

创意艺术设计的网站模板 50
查看详情 创意艺术设计的网站模板

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

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

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 <iostream>
#include <thread>
#include <vector>
#include <mutex>
#include <chrono>

// 使用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<std::thread> 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;
}
登录后复制

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

以上就是如何在C++中实现单例模式_C++单例模式设计与实现的详细内容,更多请关注php中文网其它相关文章!

最佳 Windows 性能的顶级免费优化软件
最佳 Windows 性能的顶级免费优化软件

每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。

下载
来源:php中文网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
开源免费商场系统广告
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习

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