• c++设计模式


    一、单例模式

    若有class A,整个程序中保证A类只有一个对象。
    1.为了保证只有一个实例,那么就不能让A类随意创建对象,也就不能调用构造函数,那么就需要把构造函数私有化
    2.需要私有的静态当前类的指针成员变量
    私有:保证无法在类外对成员变量进行操作。
    静态:保证类的对向只有一个。
    3.需要一个函数GetInstance()来返回单例模式的对象,因为构造函数私有化所以无法在类外构造对象。那么GetInstance()函数就作为静态接口,直接通过类名来调用函数。由于静态函数只能调用静态变量,因此A类中的成员变量也需要是静态。由于成员变量是静态的,所以要在类外进行初始化。
    4.**对象释放的问题:**由于单例模式只有一个对象,所以占用内存很少,不用专门释放内存,等到程序结束后系统将所有内存回收即可。

    1.懒汉模式

    第一次调用获取实例的函数GetInstance()时才创建对象。

    //懒汉模式
    class SingletonLazy{
    private:
    	//1.构造函数私有化
        SingletonLazy(){}
        //2.私有的静态当前类的指针成员变量
        static SingletonLazy* pSingleton;
        
    public:
    	//3.获取对象的静态接口
        static SingletonLazy* GetInstance(){
            if(pSingleton == nullptr){
                pSingleton = new SingletonLazy;
            }
            return pSingleton;
        }
    };
    SingletonLazy* SingletonLazy::pSingleton = nullptr;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    1)内部静态变量的懒汉实现

    内部静态变量的懒汉实现
    template <typename T>
    class Singleton
    {
    public:
        // 获取单实例对象
        static T &GetInstance()
        {
            // 局部静态特性的方式实现单实例
            static T single;
            return single;
        }
        // 禁止外部复制构造
        Singleton(const Singleton &single) = delete;
    
        // 禁止外部赋值操作
        const Singleton &operator=(const Singleton &single) = delete;
    
        // 禁止外部析构
        virtual ~Singleton(){}
    protected:
        Singleton(){}
    
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    如果在变量初始化过程中,多个线程同时进入声明,那么并发执行将会等待初始化完成。

    如果多个线程同时尝试访问变量的声明static T single;,并且在变量正在初始化的过程中,这些线程的执行将会同步进行。线程将会等待初始化完成,然后再继续执行。
    这个行为确保了同一时间只有一个线程能够初始化静态局部变量,避免了竞争条件和不一致的状态。它保证了在任何线程被允许访问变量之前,变量都会完全初始化。因此,在提供的代码中,如果多个线程尝试同时访问单例的 GetInstance() 方法,并且在静态局部变量初始化过程中,这些并发执行的线程将会等待初始化完成。这样确保了线程安全性,并消除了在初始化过程中可能出现的并发访问问题。

    2.饿汉模式

    直接在类外初始化对象时直接创建。在main函数执行之前就已经创建好对象。

    //饿汉模式
    class SingletonHungry{
    private:
        //1.构造函数私有化
        SingletonHungry(){}
        //2.私有的静态当前类的指针成员变量
        static SingletonHungry* pSingleton;
    
    public:
        //3.获取对象的静态接口
        static SingletonHungry* GetInstance(){
            return pSingleton;
        }
    };
    SingletonHungry* SingletonHungry::pSingleton = new SingletonHungry;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    单例模式遇到多线程

    1.懒汉模式在GetInstance函数中创建对象,那么如果多线程同时调用GetInstance函数时,那么线程不安全。
    2.饿汉模式在main函数执行前就已经创建好了对象,就不会同时对单例对对象进行操作,所以线程安全。

  • 相关阅读:
    5-羧基四甲基罗丹明,CAS号: 91809-66-4
    一起学docker系列之三docker的详细安装步骤
    【牛客网】链表中倒数第k个结点、CM11 链表分割、OR36 链表的回文结构
    MFC控制IDC_STATIC的大小和颜色
    debug 内核自动加载模块事件及禁止用户加载内核模块配置
    前端如何实现网页变灰功能的?
    2023年全球市场蓝宝石基AlN模板总体规模、主要生产商、主要地区、产品和应用细分研究报告
    Vue3开始
    MySQL8.0.x 版本安装步骤傻瓜式教程【官方版】
    PTA 7-185 组个最小数
  • 原文地址:https://blog.csdn.net/qq_43389847/article/details/133870465