• C++设计模式 单例模式(Singleton)


    对象性能模式

    面向对象很好地解决了"抽象”的问题,但是必不可免地要付出一定的代价。对于通常情况来讲,面向对象的成本大都可以忽略不计。但是某些情况,面向对象所带来的成本必须谨慎处理。

    典型模式

    Singleton

    单例模式其意图是:保证一个类只有一个实例,并提供一个访问它的全局访问点。

    • 为了防止外部类构造实例,需要将构造函数的访问权限标记为protected或private;
    • 需要提供全局访问点,就需要在类中定义一个static函数,返回在类内部唯一构造的实例。

    线程非安全版本

    #include <iostream>
    
    class Singleton{
    private:
        Singleton(){
            std::cout<<"constructor called!"<<std::endl;
        }
        Singleton(Singleton&)=delete;
        Singleton& operator=(const Singleton&)=delete;
        static Singleton* m_instance_ptr;
    public:
        ~Singleton(){
            std::cout<<"destructor called!"<<std::endl;
        }
        static Singleton* get_instance(){
            if(m_instance_ptr==nullptr){
                  m_instance_ptr = new Singleton;
            }
            return m_instance_ptr;
        }
        void use() const { std::cout << "in use" << std::endl; }
    };
    
    Singleton* Singleton::m_instance_ptr = nullptr;
    
    int main(){
        Singleton* instance = Singleton::get_instance();
        Singleton* instance_2 = Singleton::get_instance();
        return 0;
    }
    

    线程安全版本,但锁的代价过高

    #include <iostream>
    #include <mutex>
    
    class Singleton
    {
    private:
        Singleton()
        {
            std::cout << "constructor called!" << std::endl;
        }
        Singleton(Singleton &) = delete;
        Singleton &operator=(const Singleton &) = delete;
        static Singleton *m_instance;
        static std::mutex m_mtx;
    
    public:
        ~Singleton()
        {
            std::cout << "destructor called!" << std::endl;
        }
        static Singleton *get_instance()
        {
            std::lock_guard<std::mutex> lk{m_mtx};
            if (m_instance == nullptr)
            {
                m_instance = new Singleton();
            }
            return m_instance;
        }
    };
    
    Singleton *Singleton::m_instance = nullptr;
    std::mutex Singleton::m_mtx;
    
    int main()
    {
        Singleton *instance = Singleton::get_instance();
        Singleton *instance_2 = Singleton::get_instance();
        return 0;
    }
    

    双检查锁,但由于内存读写reorder不安全

    #include <iostream>
    #include <mutex>
    
    class Singleton
    {
    private:
        Singleton()
        {
            std::cout << "constructor called!" << std::endl;
        }
        Singleton(Singleton &) = delete;
        Singleton &operator=(const Singleton &) = delete;
        static Singleton *m_instance;
        static std::mutex m_mtx;
    
    public:
        ~Singleton()
        {
            std::cout << "destructor called!" << std::endl;
        }
        static Singleton *get_instance()
        {
            if (m_instance == nullptr)
            {
                std::lock_guard<std::mutex> lk{m_mtx};
                if (m_instance == nullptr)
                {
                    m_instance = new Singleton();
                }
            }
            return m_instance;
        }
    };
    
    Singleton *Singleton::m_instance = nullptr;
    std::mutex Singleton::m_mtx;
    
    int main()
    {
        Singleton *instance = Singleton::get_instance();
        Singleton *instance_2 = Singleton::get_instance();
        return 0;
    }
    

    线程安全、内存安全的(智能指针,锁)

    #include <iostream>
    #include <memory>
    #include <mutex>
    class Singleton
    {
    public:
        typedef std::shared_ptr<Singleton> Ptr;
        ~Singleton()
        {
            std::cout << "destructor called!" << std::endl;
        }
        Singleton(Singleton &) = delete;
        Singleton &operator=(const Singleton &) = delete;
        static Ptr get_instance()
        {
            if (m_instance_ptr == nullptr)
            {
                std::lock_guard<std::mutex> lk(m_mutex);
                if (m_instance_ptr == nullptr)
                {
                    m_instance_ptr = std::shared_ptr<Singleton>(new Singleton);
                }
            }
            return m_instance_ptr;
        }
    
    private:
        Singleton()
        {
            std::cout << "constructor called!" << std::endl;
        }
        static Ptr m_instance_ptr;
        static std::mutex m_mutex;
    };
    
    Singleton::Ptr Singleton::m_instance_ptr = nullptr;
    std::mutex Singleton::m_mutex;
    
    int main()
    {
        Singleton::Ptr instance = Singleton::get_instance();
        Singleton::Ptr instance2 = Singleton::get_instance();
        return 0;
    }
    

    使用静态局部变量安全又高效

    #include <iostream>
    
    class Singleton
    {
    public:
        ~Singleton()
        {
            std::cout << "destructor called!" << std::endl;
        }
        Singleton(const Singleton &) = delete;
        Singleton &operator=(const Singleton &) = delete;
        static Singleton &get_instance()
        {
            static Singleton instance;
            return instance;
        }
    
    private:
        Singleton()
        {
            std::cout << "constructor called!" << std::endl;
        }
    };
    
    int main(int argc, char *argv[])
    {
        Singleton &instance_1 = Singleton::get_instance();
        Singleton &instance_2 = Singleton::get_instance();
        return 0;
    }
    
    
  • 相关阅读:
    Python用户交互
    Python中的变量和常量
    Python的第一个程序:‘Hello World!’
    idea和pycharm激活方法
    Python环境准备(安装python解释器)
    Python简介
    编程与编程语言
    Linux下升级安装Python-3.6.2版本
    yum安装php5.5,php5.6和php7.0
    Postfix邮件黑名单和白名单
  • 原文地址:https://www.cnblogs.com/chengmf/p/15998136.html
Copyright © 2020-2023  润新知