C++ 单例模式详解

单例模式是一种创建型设计模式,它确保一个类只有一个实例,并提供一个全局访问点来访问该实例。

概念解析

单例模式的核心思想是:

  1. 限制类的实例化次数,确保在整个应用程序中只有一个实例存在

  2. 提供对该实例的全局访问点

  3. 控制共享资源的访问

主要特点

  1. 私有构造函数:防止外部通过new来创建实例

  2. 静态实例成员:保存唯一的实例

  3. 静态访问方法:提供全局访问点(通常命名为getInstance())

  4. 线程安全:需要考虑多线程环境下的安全性

代码示例

下面是一个完整的单例模式示例,包含详细注释和多种实现方式:

复制代码
#include <iostream>
#include <mutex>
#include <atomic>

// 版本1:基础单例(非线程安全)
class SingletonV1 {
private:
    static SingletonV1* instance; // 静态实例指针
    
    // 私有构造函数,防止外部实例化
    SingletonV1() {
        std::cout << "SingletonV1 实例创建" << std::endl;
    }
    
    // 防止拷贝和赋值
    SingletonV1(const SingletonV1&) = delete;
    SingletonV1& operator=(const SingletonV1&) = delete;
    
public:
    // 获取单例实例的静态方法
    static SingletonV1* getInstance() {
        if (instance == nullptr) {
            instance = new SingletonV1();
        }
        return instance;
    }
    
    void doSomething() {
        std::cout << "SingletonV1 正在执行操作" << std::endl;
    }
    
    // 用于测试的析构函数
    ~SingletonV1() {
        std::cout << "SingletonV1 实例销毁" << std::endl;
    }
};

// 初始化静态成员
SingletonV1* SingletonV1::instance = nullptr;

// 版本2:线程安全的单例(使用锁)
class SingletonV2 {
private:
    static SingletonV2* instance;
    static std::mutex mtx; // 互斥锁
    
    SingletonV2() {
        std::cout << "SingletonV2 实例创建" << std::endl;
    }
    
    SingletonV2(const SingletonV2&) = delete;
    SingletonV2& operator=(const SingletonV2&) = delete;
    
public:
    // 线程安全的获取实例方法
    static SingletonV2* getInstance() {
        std::lock_guard<std::mutex> lock(mtx); // 加锁
        if (instance == nullptr) {
            instance = new SingletonV2();
        }
        return instance;
    }
    
    void doSomething() {
        std::cout << "SingletonV2 正在执行操作" << std::endl;
    }
    
    ~SingletonV2() {
        std::cout << "SingletonV2 实例销毁" << std::endl;
    }
};

// 初始化静态成员
SingletonV2* SingletonV2::instance = nullptr;
std::mutex SingletonV2::mtx;

// 版本3:更高效的线程安全单例(双重检查锁定)
class SingletonV3 {
private:
    static SingletonV3* instance;
    static std::mutex mtx;
    
    SingletonV3() {
        std::cout << "SingletonV3 实例创建" << std::endl;
    }
    
    SingletonV3(const SingletonV3&) = delete;
    SingletonV3& operator=(const SingletonV3&) = delete;
    
public:
    // 双重检查锁定模式
    static SingletonV3* getInstance() {
        if (instance == nullptr) { // 第一次检查
            std::lock_guard<std::mutex> lock(mtx); // 加锁
            if (instance == nullptr) { // 第二次检查
                instance = new SingletonV3();
            }
        }
        return instance;
    }
    
    void doSomething() {
        std::cout << "SingletonV3 正在执行操作" << std::endl;
    }
    
    ~SingletonV3() {
        std::cout << "SingletonV3 实例销毁" << std::endl;
    }
};

// 初始化静态成员
SingletonV3* SingletonV3::instance = nullptr;
std::mutex SingletonV3::mtx;

// 版本4:C++11最推荐的实现(Meyer's Singleton)
class SingletonV4 {
private:
    SingletonV4() {
        std::cout << "SingletonV4 实例创建" << std::endl;
    }
    
    SingletonV4(const SingletonV4&) = delete;
    SingletonV4& operator=(const SingletonV4&) = delete;
    
public:
    // C++11保证局部静态变量的初始化是线程安全的
    static SingletonV4& getInstance() {
        static SingletonV4 instance; // 线程安全的初始化
        return instance;
    }
    
    void doSomething() {
        std::cout << "SingletonV4 正在执行操作" << std::endl;
    }
    
    ~SingletonV4() {
        std::cout << "SingletonV4 实例销毁" << std::endl;
    }
};

// 版本5:使用atomic的现代C++实现
class SingletonV5 {
private:
    static std::atomic<SingletonV5*> instance;
    static std::mutex mtx;
    
    SingletonV5() {
        std::cout << "SingletonV5 实例创建" << std::endl;
    }
    
    SingletonV5(const SingletonV5&) = delete;
    SingletonV5& operator=(const SingletonV5&) = delete;
    
public:
    // 使用atomic的现代实现
    static SingletonV5* getInstance() {
        SingletonV5* tmp = instance.load(std::memory_order_acquire);
        if (tmp == nullptr) {
            std::lock_guard<std::mutex> lock(mtx);
            tmp = instance.load(std::memory_order_relaxed);
            if (tmp == nullptr) {
                tmp = new SingletonV5();
                instance.store(tmp, std::memory_order_release);
            }
        }
        return tmp;
    }
    
    void doSomething() {
        std::cout << "SingletonV5 正在执行操作" << std::endl;
    }
    
    ~SingletonV5() {
        std::cout << "SingletonV5 实例销毁" << std::endl;
    }
};

// 初始化静态成员
std::atomic<SingletonV5*> SingletonV5::instance{nullptr};
std::mutex SingletonV5::mtx;

int main() {
    std::cout << "=== 单例模式演示 ===" << std::endl;
    
    // 测试基础单例
    std::cout << "\n测试 SingletonV1 (基础单例):" << std::endl;
    SingletonV1::getInstance()->doSomething();
    SingletonV1::getInstance()->doSomething();
    
    // 测试线程安全单例
    std::cout << "\n测试 SingletonV2 (线程安全-锁):" << std::endl;
    SingletonV2::getInstance()->doSomething();
    SingletonV2::getInstance()->doSomething();
    
    // 测试双重检查锁定单例
    std::cout << "\n测试 SingletonV3 (双重检查锁定):" << std::endl;
    SingletonV3::getInstance()->doSomething();
    SingletonV3::getInstance()->doSomething();
    
    // 测试Meyer's单例
    std::cout << "\n测试 SingletonV4 (Meyer's Singleton):" << std::endl;
    SingletonV4::getInstance().doSomething();
    SingletonV4::getInstance().doSomething();
    
    // 测试atomic单例
    std::cout << "\n测试 SingletonV5 (atomic实现):" << std::endl;
    SingletonV5::getInstance()->doSomething();
    SingletonV5::getInstance()->doSomething();
    
    return 0;
}

模式优势

  1. 控制实例数量:确保一个类只有一个实例存在

  2. 全局访问点:提供对实例的全局访问,避免使用全局变量

  3. 延迟初始化:实例只在第一次被请求时创建

  4. 资源管理:对于需要集中管理的资源(如配置、连接池等)非常有用

适用场景

  1. 当类只能有一个实例且客户端可以从众所周知的访问点访问它时

  2. 当唯一实例应该通过子类化可扩展,并且客户端应该无需修改代码就能使用扩展后的实例时

  3. 需要严格控制全局变量的场景

  4. 需要频繁创建和销毁的对象,但又想节省系统资源时

实现注意事项

  1. 线程安全:多线程环境下需要考虑同步问题

  2. 析构问题:全局静态实例的销毁顺序可能导致问题

  3. 测试困难:单例可能使单元测试变得困难,因为它保持了全局状态

  4. 隐藏依赖:单例的使用可能导致代码的依赖关系不明显

相关推荐
万邦科技Lafite20 分钟前
京东按图搜索京东商品(拍立淘) API (.jd.item_search_img)快速抓取数据
开发语言·前端·数据库·python·电商开放平台·京东开放平台
ha20428941942 小时前
Linux操作系统学习之---基于环形队列的生产者消费者模型(毛坯版)
linux·c++·学习
Never_Satisfied2 小时前
在JavaScript / Node.js / 抖音小游戏中,使用tt.request通信
开发语言·javascript·node.js
爱吃小胖橘2 小时前
Unity资源加载模块全解析
开发语言·unity·c#·游戏引擎
千里镜宵烛4 小时前
Lua-迭代器
开发语言·junit·lua
渡我白衣4 小时前
C++ 同名全局变量:当符号在链接器中“相遇”
开发语言·c++·人工智能·深度学习·microsoft·语言模型·人机交互
淮北4945 小时前
html + css +js
开发语言·前端·javascript·css·html
源码_V_saaskw5 小时前
JAVA国际版二手交易系统手机回收好物回收发布闲置商品系统源码支持APP+H5
java·开发语言·微信·智能手机·微信小程序·小程序
java1234_小锋6 小时前
PyTorch2 Python深度学习 - PyTorch2安装与环境配置
开发语言·python·深度学习·pytorch2