导读:本期聚焦于小伙伴创作的《C++如何实现单例模式?单例模式的经典实现与进阶优化方案有哪些?》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《C++如何实现单例模式?单例模式的经典实现与进阶优化方案有哪些?》有用,将其分享出去将是对创作者最好的鼓励。

单例模式是C++设计模式中的基础且高频使用的模式,其核心价值在于控制类的实例化过程,保证全局范围内该类只有一个实例对象,同时提供统一的访问接口。这种模式在需要全局共享资源、控制唯一操作的场景中非常实用,比如日志管理器、配置管理器、数据库连接池等场景都会用到单例模式。

C++如何实现单例模式?单例模式的经典实现与进阶优化方案有哪些?

单例模式的基础实现方式

1. 饿汉式单例

饿汉式单例的核心思路是在程序启动阶段就完成实例的创建,依赖C++全局变量的初始化特性,天然具备线程安全性,因为全局变量的初始化在main函数执行前就已经完成。

#include <iostream>

class HungrySingleton {
private:
    // 私有化构造函数,禁止外部直接实例化
    HungrySingleton() {
        std::cout << "饿汉式单例实例创建" << std::endl;
    }
    // 禁止拷贝构造函数和赋值运算符
    HungrySingleton(const HungrySingleton&) = delete;
    HungrySingleton& operator=(const HungrySingleton&) = delete;

public:
    // 提供全局访问点
    static HungrySingleton* getInstance() {
        return instance;
    }

    // 示例方法
    void doSomething() {
        std::cout << "饿汉式单例执行操作" << std::endl;
    }

private:
    // 静态实例,程序启动时初始化
    static HungrySingleton* instance;
};

// 类外初始化静态成员
HungrySingleton* HungrySingleton::instance = new HungrySingleton();

int main() {
    HungrySingleton* singleton = HungrySingleton::getInstance();
    singleton->doSomething();
    return 0;
}

饿汉式的优点是实现简单、线程安全,缺点是如果单例实例占用资源较多,且程序全程没有使用该实例,会造成资源浪费。

2. 基础懒汉式单例

懒汉式单例采用延迟加载的思路,只有在第一次调用getInstance方法时才创建实例,能够避免不必要的资源占用,但基础版本存在线程安全问题。

#include <iostream>

class LazySingleton {
private:
    LazySingleton() {
        std::cout << "懒汉式单例实例创建" << std::endl;
    }
    LazySingleton(const LazySingleton&) = delete;
    LazySingleton& operator=(const LazySingleton&) = delete;

public:
    static LazySingleton* getInstance() {
        // 第一次调用时才创建实例
        if (instance == nullptr) {
            instance = new LazySingleton();
        }
        return instance;
    }

    void doSomething() {
        std::cout << "懒汉式单例执行操作" << std::endl;
    }

private:
    static LazySingleton* instance;
};

LazySingleton* LazySingleton::instance = nullptr;

int main() {
    LazySingleton* singleton = LazySingleton::getInstance();
    singleton->doSomething();
    return 0;
}

在单线程环境下这个实现没有问题,但多线程场景下,多个线程可能同时判断instance == nullptr,导致创建多个实例,违反单例模式的核心要求。

进阶优化:线程安全的单例实现

1. 加锁实现的线程安全懒汉式

针对基础懒汉式的线程安全问题,最直接的优化方式是在实例创建前加互斥锁,保证同一时间只有一个线程能执行实例创建逻辑。

#include <iostream>
#include <mutex>

class ThreadSafeLazySingleton {
private:
    ThreadSafeLazySingleton() {
        std::cout << "线程安全懒汉式单例实例创建" << std::endl;
    }
    ThreadSafeLazySingleton(const ThreadSafeLazySingleton&) = delete;
    ThreadSafeLazySingleton& operator=(const ThreadSafeLazySingleton&) = delete;

public:
    static ThreadSafeLazySingleton* getInstance() {
        // 加锁保证线程安全
        m_mutex.lock();
        if (instance == nullptr) {
            instance = new ThreadSafeLazySingleton();
        }
        m_mutex.unlock();
        return instance;
    }

    void doSomething() {
        std::cout << "线程安全懒汉式单例执行操作" << std::endl;
    }

private:
    static ThreadSafeLazySingleton* instance;
    static std::mutex m_mutex;
};

ThreadSafeLazySingleton* ThreadSafeLazySingleton::instance = nullptr;
std::mutex ThreadSafeLazySingleton::m_mutex;

int main() {
    ThreadSafeLazySingleton* singleton = ThreadSafeLazySingleton::getInstance();
    singleton->doSomething();
    return 0;
}

这种方式虽然解决了线程安全问题,但每次调用getInstance都需要加锁解锁,会带来额外的性能开销,因为实例一旦创建完成,后续就不需要再加锁了。

2. 双重检查锁定(DCLP)优化

双重检查锁定先判断实例是否已经存在,不存在再加锁,加锁后再判断一次实例是否存在,这样既能保证线程安全,又能减少锁的性能开销。

#include <iostream>
#include <mutex>
#include <atomic>

class DCLPSingleton {
private:
    DCLPSingleton() {
        std::cout << "双重检查锁定单例实例创建" << std::endl;
    }
    DCLPSingleton(const DCLPSingleton&) = delete;
    DCLPSingleton& operator=(const DCLPSingleton&) = delete;

public:
    static DCLPSingleton* getInstance() {
        // 第一次检查,实例存在直接返回
        if (instance.load(std::memory_order_acquire) == nullptr) {
            std::lock_guard<std::mutex> lock(m_mutex);
            // 第二次检查,避免多线程同时进入第一次检查后重复创建
            if (instance.load(std::memory_order_relaxed) == nullptr) {
                instance.store(new DCLPSingleton(), std::memory_order_release);
            }
        }
        return instance.load(std::memory_order_acquire);
    }

    void doSomething() {
        std::cout << "双重检查锁定单例执行操作" << std::endl;
    }

private:
    static std::atomic<DCLPSingleton*> instance;
    static std::mutex m_mutex;
};

std::atomic<DCLPSingleton*> DCLPSingleton::instance(nullptr);
std::mutex DCLPSingleton::m_mutex;

int main() {
    DCLPSingleton* singleton = DCLPSingleton::getInstance();
    singleton->doSomething();
    return 0;
}

这里使用std::atomic配合内存序来保证指令不会重排,避免早期C++中双重检查锁定因为指令重排导致的未定义行为,是符合现代C++标准的实现方式。

3. 局部静态变量实现(C++11及以上推荐)

C++11标准规定,局部静态变量的初始化是线程安全的,编译器会保证局部静态变量只被初始化一次,因此可以用这种方式实现非常简洁且安全的单例。

#include <iostream>

class LocalStaticSingleton {
private:
    LocalStaticSingleton() {
        std::cout << "局部静态变量单例实例创建" << std::endl;
    }
    LocalStaticSingleton(const LocalStaticSingleton&) = delete;
    LocalStaticSingleton& operator=(const LocalStaticSingleton&) = delete;

public:
    static LocalStaticSingleton& getInstance() {
        // 局部静态变量,C++11保证线程安全且仅初始化一次
        static LocalStaticSingleton instance;
        return instance;
    }

    void doSomething() {
        std::cout << "局部静态变量单例执行操作" << std::endl;
    }
};

int main() {
    LocalStaticSingleton& singleton = LocalStaticSingleton::getInstance();
    singleton.doSomething();
    return 0;
}

这种实现方式不需要手动管理指针和锁,代码简洁,同时具备延迟加载、线程安全、自动释放实例的优点,是C++11及以上版本中最推荐的单例实现方式。

不同实现方式的对比

实现方式线程安全延迟加载实现复杂度适用场景
饿汉式单例实例占用资源少,程序启动即需要使用的场景
基础懒汉式仅单线程环境
加锁懒汉式低版本C++,对性能要求不高的多线程场景
双重检查锁定高版本C++,对性能要求高的多线程场景
局部静态变量极低C++11及以上版本的所有多线程场景

单例模式的注意事项

实现单例模式时除了保证实例唯一和线程安全,还需要注意几个问题:首先是禁止拷贝和赋值,避免通过拷贝构造创建新的实例;其次是如果单例实例持有资源,需要合理处理资源释放,比如局部静态变量会在程序结束时自动析构,无需手动释放;最后是不要过度使用单例模式,单例本质上是一种全局状态,过度使用会增加代码的耦合度,不利于单元测试和代码维护。

C++单例模式设计模式懒汉式单例饿汉式单例线程安全修改时间:2026-06-25 04:12:40

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。