c++中单例模式使用及说明(局部静态变量)

 更新时间:2026年05月23日 10:35:29   作者:海青橘  
这篇文章主要介绍了c++中单例模式使用及说明(局部静态变量),具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

单例模式的作用

单例模式的核心在于确保一个类只有一个实例,并为整个系统提供统一的访问入口,从而实现资源与逻辑的精简。

它通过私有化构造函数来禁止外部随意创建对象,强制所有代码通过同一个静态方法获取唯一实例。

这样做既避免了重复创建重量级对象(如配置管理器、数据库连接池)的资源浪费,也简化了对象在系统各处的传递与访问——你不需要在多个模块间手动传递同一个对象,只需通过全局访问点直接获取即可。

这种设计将对象的生命周期与访问方式标准化,让代码更聚焦于业务逻辑而非对象管理。但需警惕,过度使用单例会引入全局状态隐式耦合,增加测试复杂度,因此应严格限定于真正需要“唯一性”的场景。

总结:

  • 单例模式通过控制实例数量和提供统一访问点,实现资源管理的精简与代码结构的简化。
  • 但需注意多线程安全、单元测试难度等潜在问题,避免滥用。

单例模式(局部静态变量模式)

//静态局部变量方式实现单例模式
#include<iostream>
using namespace std;
class S {
private:
	S() {}
	S(const S&) = delete;
	S& operator=(const S&) = delete;
public:
	static S& getS() {
		static S s;
		return s;
	}
};

单例模式的应用(局部静态变量)

#include <iostream>
#include <string>
#include <unordered_map>

/**
 * 配置管理器单例类
 * 在大型项目中,通常需要一个全局唯一的配置中心来管理各种服务配置项
 * 如数据库连接信息、API密钥、服务器端口等
 */
class ConfigManager {
private:
    // 私有构造函数,防止外部直接创建实例
    ConfigManager() {
        // 在构造函数中加载默认配置
        loadDefaultConfig();
        std::cout << "ConfigManager 初始化完成,加载默认配置" << std::endl;
    }

    // 删除拷贝构造函数和赋值操作符,确保单例的唯一性
    ConfigManager(const ConfigManager&) = delete;
    ConfigManager& operator=(const ConfigManager&) = delete;

    // 加载默认配置的方法
    void loadDefaultConfig() {
        configMap["database_host"] = "localhost";
        configMap["database_port"] = "3306";
        configMap["redis_host"] = "localhost";
        configMap["redis_port"] = "6379";
        configMap["api_timeout"] = "5000"; // 毫秒
        configMap["max_connections"] = "100";
    }

    // 存储配置项的哈希表
    std::unordered_map<std::string, std::string> configMap;

public:
    /**
     * 获取单例实例的静态方法
     * C++11 标准保证 static 局部变量的初始化是线程安全的
     */
    static ConfigManager& getInstance() {
        static ConfigManager instance; // 静态局部变量,延迟初始化
        return instance;
    }

    /**
     * 获取配置值
     * @param key 配置项键名
     * @return 配置项对应的值,如果不存在则返回空字符串
     */
    std::string getConfig(const std::string& key) const {
        auto it = configMap.find(key);
        //std::map<KeyType, ValueType>::iterator it = configMap.find(key);//传统写法
        if (it != configMap.end()) {
            return it->second;
        }
        std::cout << "警告: 未找到配置项 '" << key << "'" << std::endl;
        return "";
    }

    /**
     * 设置配置值
     * 在实际项目中,这个方法可能用于动态更新配置
     * @param key 配置项键名
     * @param value 配置项值
     */
    void setConfig(const std::string& key, const std::string& value) {
        configMap[key] = value;
        std::cout << "配置项 '" << key << "' 更新为: " << value << std::endl;
    }

    /**
     * 打印所有配置项(用于调试)
     */
    void printAllConfigs() const {
        std::cout << "\n=== 当前所有配置 ===" << std::endl;
        for (const auto& pair : configMap) {
            std::cout << pair.first << " = " << pair.second << std::endl;
        }
        std::cout << "==================\n" << std::endl;
    }
};

/**
 * 模拟数据库连接类
 * 使用配置管理器获取数据库连接参数
 */
class DatabaseConnection {
public:
    DatabaseConnection() {
        // 从配置管理器获取数据库连接参数
        auto& config = ConfigManager::getInstance();
        host = config.getConfig("database_host");
        port = config.getConfig("database_port");

        std::cout << "正在连接数据库: " << host << ":" << port << std::endl;
    }

private:
    std::string host;
    std::string port;
};

/**
 * 模拟 Redis 连接类
 * 同样使用配置管理器获取 Redis 连接参数
 */
class RedisConnection {
public:
    RedisConnection() {
        // 从配置管理器获取 Redis 连接参数
        auto& config = ConfigManager::getInstance();
        host = config.getConfig("redis_host");
        port = config.getConfig("redis_port");

        std::cout << "正在连接 Redis: " << host << ":" << port << std::endl;
    }

private:
    std::string host;
    std::string port;
};

int main() {
    std::cout << "=== 大厂项目配置管理器演示 ===" << std::endl;

    // 场景1: 数据库连接器获取配置
    std::cout << "\n--- 初始化数据库连接 ---" << std::endl;
    DatabaseConnection dbConn;

    // 场景2: Redis连接器获取配置
    std::cout << "\n--- 初始化Redis连接 ---" << std::endl;
    RedisConnection redisConn;

    // 场景3: 验证单例的唯一性
    std::cout << "\n--- 验证单例模式 ---" << std::endl;
    auto& config1 = ConfigManager::getInstance();
    auto& config2 = ConfigManager::getInstance();

    if (&config1 == &config2) {
        std::cout << "验证成功: 两次获取的实例是同一个对象" << std::endl;
    }
    else {
        std::cout << "验证失败: 获取到了不同的实例" << std::endl;
    }

    // 场景4: 动态修改配置
    std::cout << "\n--- 动态修改配置 ---" << std::endl;
    auto& config = ConfigManager::getInstance();
    config.setConfig("database_host", "prod-database.company.com");
    config.setConfig("api_timeout", "10000");

    // 验证配置是否更新
    std::cout << "更新后的数据库主机: " << config.getConfig("database_host") << std::endl;
    std::cout << "更新后的API超时时间: " << config.getConfig("api_timeout") << "ms" << std::endl;

    // 场景5: 打印所有配置
    config.printAllConfigs();

    // 场景6: 模拟新连接使用更新后的配置
    std::cout << "\n--- 新连接使用更新后的配置 ---" << std::endl;
    DatabaseConnection newDbConn; // 这个连接会使用更新后的主机地址

    return 0;
}

运行结果

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • 使用C语言构建基本的二叉树数据结构

    使用C语言构建基本的二叉树数据结构

    这篇文章主要介绍了使用C语言使用C语言构建基本的二叉树数据结构,包括根据前序序列和中序序列构建二叉树的方法,需要的朋友可以参考下
    2015-08-08
  • 详解如何使用C++写一个线程安全的单例模式

    详解如何使用C++写一个线程安全的单例模式

    这篇文章主要为大家详细介绍了如何使用C++写一个线程安全的单例模式,文中的示例代码讲解详细,具有一定的学习价值,感兴趣的小伙伴可以了解一下
    2022-10-10
  • c语言颜色代码详解

    c语言颜色代码详解

    在本篇文章里小编给大家整理的是关于c语言颜色代码的知识点内容,需要的朋友们可以参考下。
    2020-02-02
  • C语言判断语句和if语句形式及多层if使用示例

    C语言判断语句和if语句形式及多层if使用示例

    这篇文章主要为大家介绍了C语言判断语句和if语句形式及多层if使用示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-09-09
  • Windows下使用Dev-C++开发基于pthread.h的多线程程序实例

    Windows下使用Dev-C++开发基于pthread.h的多线程程序实例

    下面小编就为大家带来一篇Windows下使用Dev-C++开发基于pthread.h的多线程程序实例。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-09-09
  • 实例代码分析c++动态分配

    实例代码分析c++动态分配

    这篇文章主要介绍了c++动态分配的的相关资料,文中代码简单易懂,方便大家更好的学习参考,感兴趣的朋友可以了解下
    2020-06-06
  • C语言学生成绩管理系统课程设计word版

    C语言学生成绩管理系统课程设计word版

    这篇文章主要为大家详细介绍了C语言学生成绩管理课程设计,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-12-12
  • epoll封装reactor原理剖析示例详解

    epoll封装reactor原理剖析示例详解

    这篇文章主要为大家介绍了epoll封装reactor原理剖析示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-07-07
  • 在编程语言中怎样定义队列及其使用(C++)

    在编程语言中怎样定义队列及其使用(C++)

    这篇文章主要介绍了在编程语言中怎样定义队列,本文主要根据c++来介绍,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2019-03-03
  • C语言排序算法之桶排序解析

    C语言排序算法之桶排序解析

    这篇文章主要介绍了C语言排序算法之桶排序解析,桶排序Bucket sort或所谓的箱排序,是一个排序算法,工作的原理是将数组分到有限数量的桶里,每个桶再分别排序,大部分是在分桶时,即插入时就排序了,需要的朋友可以参考下
    2023-10-10

最新评论