• C++单例模板:使用宏函数实现


    C++单例模板:使用宏函数实现

      在我们日常开发中,无可避免需要使用单例模式进行设计类对象,那么实际上我们写单例格式基本都是一样的,那么每次都要写几乎一模一样的代码来实现我们需要的单例对象是不是会觉得很累?下面博主提供一种单例模板来完成我们日常设计单例类,提高工作效率。既然封装了,那么当然是封装一个线程安全的单例模板,如下:

    ISingleton.hpp

    #pragma once
    #include 
    #include 
    #include 
    #include 
    
    
    /******************************************************************************/
    /**********************ufgnix0802:单例宏定义(线程安全)*************************/
    /******************************************************************************/
    
    #define SINGLETON_CLASS_DEFAULT(Class)                                          \
        private:                                                                    \
            Class() {}                                                              \
            ~Class() {}                                                             \
            Class(Class &other) {}                                                  \
            Class(const Class &other) {}                                            \
            Class& operator=(Class &other) {}                                       \
            Class& operator=(const Class &other) {}                                 \
    
    
    #define SINGLETON_CLASS_FUNC_DECL(Class)                                        \
        public:                                                                     \
            static Class& Ins();                                                    \
        private:                                                                    \
            static void InitSingleton();                                            \
                                                                                    \
            static void Release();                                                  \
                                                                                    \
            SINGLETON_CLASS_DEFAULT(Class)                                          \
    private:                                                                        \
        static std::once_flag m_singletonFlag;                                      \
        static Class* m_ins;
    
    /* https://liam.page/2020/10/27/implement-a-singleton-class-template-in-cxx/ */                         
    /* https://liam.page/2017/01/17/layers-and-operation-system/#CPU-%E5%8A%A8%E6%80%81%E8%B0%83%E5%BA%A6 */
    
    #define SINGLETON_CLASS_FUNC_IMPL(Class)                                        \
        Class& Class::Ins() {                                                       \
            /* 使用双重检查,外层检查是为了避免锁住过大的面积,从而导致锁的竞争特别频繁;*/\
            /* 内层检查是为了确保只在其它线程没有抢占锁完成初始化工作而设计。*/           \
            /* 这种做法在Java下是正确的,但是在C++下则没有保证。*/                      \
            /* std::once_flag 和 std::call_once:它们内部利用互斥量和条件变量组合,*/   \
            /* 实现这样的语义。值得一提的是,如果执行过程中抛出异常,标准库的设施不认为 */ \
            /* 这是一次「成功的执行」。于是其他线程可以继续抢占锁来执行函数。 */          \
            /* std:call_once确保函数或代码片段在多线程环境下,只需要执行一次。 */        \
            std::call_once(m_singletonFlag, &Class::InitSingleton);                 \
            assert(m_ins != NULL);                                                  \
            return *m_ins;                                                          \
        }                                                                           \
                                                                                    \
        void Class::InitSingleton() {                                               \
            m_ins = new Class;                                                      \
            if (m_ins) {                                                            \
            /* C 库函数 int atexit(void (*func)(void)) 当程序正常终止时,调用指定的*/  \
            /* 函数func。您可以在任何地方注册你的终止函数,*/                           \
            /* 但它会在程序终止的时候被调用。*/                                        \
                    ::atexit(Release);                                              \
            }                                                                       \
        }                                                                           \
                                                                                    \
        void Class::Release() {                                                     \
             if (m_ins) {                                                           \
                  delete m_ins;                                                     \
                  m_ins = NULL;                                                     \
             }                                                                      \
        }                                                                   
    
    
    #define SINGLETON_CLASS_VARIABLE_IMPL(Class)                                    \
            std::once_flag Class::m_singletonFlag;                                  \
            Class* Class::m_ins = NULL;
    
    
    #define SINGLETON_CLASS_IMPL(Class)                                             \
            SINGLETON_CLASS_VARIABLE_IMPL(Class)                                    \
            SINGLETON_CLASS_FUNC_IMPL(Class)                                        
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77

    使用方式

      注意,如果我们的单例类对象在.hpp文件中那么可能出现重定义的问题,博主设计的单例模板,只适用于.h和.cpp,即声明和定义分开单例类对象。

    Aclass.h

    #include "ISingleton.hpp"
    
    
    class Aclass {
        //声明
        SINGLETON_CLASS_FUNC_DECL(Aclass)
    
    public:
        int a;
        
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    Aclass.cpp

    #include "Aclass.h"
    
    //定义
    SINGLETON_CLASS_IMPL(Aclass);
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    main.c

    #include "Aclass.h"
    int main() {
        //Aclass a;  err
        Aclass::Ins().a = 5;
        std::cout << Aclass::Ins().a << std::endl;
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

      运行结果:
    效果图

  • 相关阅读:
    AUTOSAR汽车电子嵌入式编程精讲300篇-基于 CAN 总线的车辆数据采集与远程监控系统研发(下)
    如何使用 UltraEdit 加密和解密您的文本文件
    JS中什么是回调函数?
    时间空间复杂度分析--选择排序算法
    【FPGA教程案例72】基础操作2——Xilinx原语学习及应用2
    java-net-php-python-jsp音像店租赁录像计算机毕业设计程序
    HACKTHEBOX——Shocker
    ITSS认证现场的评估过程基本步骤
    内存池的实现与场景分析
    深度学习——序列模型and数学符号
  • 原文地址:https://blog.csdn.net/qq135595696/article/details/128121759