单例模式-Singleton

一、概念

单例 Singleton 是设计模式的一种,其特点是只提供唯一个类的实例,具有全局变量的特点,在任何位置都可以通过接口Instance() 获取到那个唯一实例。

二、使用场景

当代码中需要唯一一个实例存在的类的全局变量的时候才使用单例,比如管理器之类的。

三、如何才能写一个单例

  • static  保证只有一个实例;
  • 构造函数的访问方式设为private  避免用户自己实例化类;
  • Singleton(Singleton&)=delete  禁止拷贝;
  • Singleton& operator=(const Singleton&)=delete   禁止赋值;
  • 用户通过接口Instance() 获取实例   使用 static 类成员函数;

四、如何才能写一个好单例

尽可能小;尽可能简单;保证线程安全;内存不泄露;

五、最推荐的懒汉式单例—局部静态变量

  1. 通过局部静态变量的特性保证了线程安全 (C++11, GCC > 4.3, VS2015支持该特性);
  2. 注意在使用的时候需要声明单例的引用 Single& 才能获取对象。
#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;
}

这种方法又叫做 Meyers' SingletonMeyer's的单例, 是著名的写出《Effective C++》系列书籍的作者 Meyers 提出的。所用到的特性是在C++11标准中的Magic Static特性:

If control enters the declaration concurrently while the variable is being initialized, the concurrent execution shall wait for completion of the initialization.
如果当变量在初始化的时候,并发同时进入声明语句,并发线程将会阻塞等待初始化结束。

这样保证了并发线程在获取静态局部变量的时候一定是初始化过的,所以具有线程安全性。 

六、单例模板

template<typename  T>
class Singleton{
public:
    static T& instance(){
        //初始化Manager,调用Manager的构造函数,同时调用Singleton的构造函数
        static T _instance;
        return _instance;
    }
protected:
    virtual ~Singleton(){std::cout<<u8"~Singleton()..."<<std::endl;}
    //protected修饰的构造函数才能被别人继承
    Singleton(){std::cout<<u8"Singleton()..."<<std::endl;}
    Singleton(const Singleton&)=delete;
    Singleton& operator=(const Singleton&)=delete;
};

class Manager: public Singleton<Manager>{
   // friend能让Singleton<T>访问到Manager的构造函数
    friend class Singleton<Manager>;
private:
    Manager(){std::cout<<u8"Manager()..."<<std::endl;}
    ~Manager(){std::cout<<u8"~Manager()..."<<std::endl;}
    Manager(const Manager&)=delete;
    Manager& operator=(const Manager&)=delete;
};

int main()
{
    Manager& singleton = Manager::instance();
    Manager& singleton2 = Manager::instance();
    return 0;
}

//输出
//Singleton()...
//Manager()...
//~Manager()...
//~Singleton()...

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

搓搓程序狗

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值