支持HW团队,就支付宝领取下面的红包吧! (打开支付宝就能领取!er1OEj73Uj), (打开支付宝收索“516503473”), 你领取消费,HW有奖励。红包使用无条件限制,有条件请注意是不是有病毒。

Login or Sign up | Validate
| Search
HelloWorld论坛 : > 计算机科学、技术、教学> 编程入门> c、c++基础> 【转】单例模式之懒汉、饿汉以及C++11中的单例模式
 
 
 
 
类别:其他 阅读:669 评论:0 时间:March 13, 2020, 9:53 p.m. 关键字:

 

 
原文链接:https://blog.csdn.net/qq_41209741/article/details/98969277
 
文章目录
单例模式分为两种
        懒汉模式一:双检索+自动回收
        懒汉模式二:静态局部变量,避免自己回收资源
        饿汉模式一
        饿汉模式二(boost实现)
        C++11中借助可变参数模板实现的单例
单例模式分为两种
懒汉模式:第一次调用时才初始化,有延迟加载的效果,以时间换空间
优点:第一次使用实例对象时,创建对象。进程启动无负载。多个单例实例启动顺序自由控制。
缺点:复杂
饿汉模式:程序开始就初始化,以空间换时间
优点:简单
缺点:可能会导致进程启动慢,且如果有多个单例类对象实例启动顺序不确定。
懒汉模式一:双检索+自动回收
class Singleton {
public:
        Singleton * GetInsTance()
        {
                if (m_PInstance == nullptr)
                {
                        m_tex.lock();
                        if (m_PInstance == nullptr)
                                m_PInstance = new Singleton();
                        m_tex.unlock();
                }
                return m_PInstance;
        }

        //实现一个内嵌垃圾回收类
        class CGarbo {
                ~CGarbo()
                {
                        if (m_PInstance != nullptr)
                        {
                                delete Singleton::m_PInstance;
                                Singleton::mPInstance = nullptr;
                        }
                }
        };
        //定义一个静态变量,程序结束时,系统会自动调用它的析构函数,从而释放单例
        static CGarbo cgarbo;
private:
        //构造函数私有,防拷贝
        Singleton(){}
        Singleton(Singleton const&) = delete;
        Singleton& operator=(Singleton &) = delete;

private:
        static Singleton* m_PInstance;
        static mutex m_tex;
};
Singleton* Singleton::m_PInstance = nullptr;
mutex Singleton::m_tex;
Singleton::CGarbo cgarbo;
懒汉模式二:静态局部变量,避免自己回收资源
       支持多线程(在C++0X以后,要求编译器保证静态变量初始化的线程安全性,可以不加锁。但C++ 0X以前,仍需要加锁。)
class Singleton
{
public:
    static Singleton* GetInstance()
    { 
        static Singleton instance;  
        return &instance;
    }
 
private:
    Singleton() {};
    Singleton(const Singleton &) = delete;
    Singleton & operator = (const Singleton &) = delete;
};
饿汉模式一
class Singleton
{
public:
 
    static Singleton* GetInstance()
    {
        return &m_instance;
    }
 
private:
    Singleton(){};
    Singleton(Singleton const&); 
    Singleton& operator=(Singleton const&); 
 
    static Singleton m_instance;
};
 
Singleton Singleton::m_instance;  // 在程序入口之前就完成单例对象的初始化
       在C++中非局部静态对象的初始化顺序的不确定性可能会导致上述饿汉模式工作不正常。考虑: 如果有两个这样的单例类,将分别生成单例对象A, 单例对象B. 它们分别定义在不同的编译单元(cpp中), 而A的初始化依赖于B 【 即A的构造函数中要调用B::GetInstance() ,而此时B::m_instance 可能还未初始化,显然调用结果就是非法的 】, 所以说只有B在A之前完成初始化程序才能正确运行,而这种跨编译单元的初始化顺序编译器是无法保证的。
 
饿汉模式二(boost实现)
       boost 的实现方式是:单例对象作为静态局部变量,然后增加一个辅助类,并声明一个该辅助类的类静态成员变量,在该辅助类的构造函数中,初始化单例对象。以下为代码
 
class Singleton
{
public:
    static Singleton* GetInstance()
    {
        static Singleton instance;
        return &instance;
    }
 
protected:
    // 辅助代理类
    struct Object_Creator
    {
        Object_Creator()
        {
            Singleton::GetInstance();
        }
    };
    static Object_Creator _object_creator;
 
    Singleton() {}
    ~Singleton() {}
};
 
Singleton::Object_Creator Singleton::_object_creator; 
       首先,代理类这个外部变量初始化时,在其构造函数内部调用 Singleton::GetInstance();从而间接完成单例对象的初始化,这就通过该代理类实现了饿汉模式的特性。
       其次,仍然考虑第三种模式的缺陷。 当A的初始化依赖于B, 【 即A的构造函数中要调用B::GetInstance() ,而此时B::m_instance 可能还未初始化,显然调用结果就是非法的 】 现在就变为【在A的构造函数中要调用B::GetInstance() ,如果B尚未初始化,就会引发B的初始化】,所以在不同编译单元内全局变量的初始化顺序不定的问题就随之解决。
 
C++11中借助可变参数模板实现的单例
template <typename T>
class Singleton {
public:
        template<typename...Args>
        static T* Instance(Args&&...args)
        {
                if (m_pInstance == nullptr)
                        m_pInstance = new T(std::forward<Args>(args)...);//完美转发
                return m_pInstance;
        }
        //获取单例
        static T* GetInstance()
        {
                if (m_pInstance == nullptr)
                        throw std::logic_error("the instance is not init,please initialzer the instance first!");
                return m_pInstance;
        }
        static void DestoryInstance()
        {
                delete m_pInstance;
                m_pInstance = nullptr;
        }
private:
        Singleton(void);
        ~Singleton(void);
        Singleton(const Singleton&) = delete;
        Singleton&operator = (const Singleton &) = delete;

private:
        static Singleton * m_pInstance;
};

 

[挂载人]初学MPEG [审核人]初学MPEG 推荐

个人签名--------------------------------------------------------------------------------

Please Login (or Sign Up) to leave a comment