单例模式

单例模式有多种写法, 最简单的一种是:

 

class Test
{
private:
    Test() {}
private:
    static Test* instance;
public:
    static Test* GetInstance()
    {
        if (!Test)
        {
            instance = new Test;
        }
        return instance;
    }
};

  

但是这种形式,在多线程中使用可能出错,在还没创建对象,多个线程同时调用GetInstance()时,假设线程1执行了

 

if (!Test)

 

这时切换线程了,cpu去执行线程2的 if (!Test) , 线程2创建对象 instance = new Test;

然后cpu回来执行线程1的创建对象 instance = new Test;

这样 new 操作可能执行了多次,创建了多个实例。

 

总结:虽然出错几率很小,但还是有,只发生在第一次创建实例时,一旦创建实例成功,就再也不会出错了。

 

第二种:

 

class Test
{
private:
    Test() {}
public:
    static Test& GetInstance()
    {
        static Test instance;
        return instance;
    }
};

 

这种方式很棒, 像下面这种使用方法,很完美:

 

                                 Test::GetInstance().Start();

 

创建一个类的实例,并启动这个模块。

 

但这只适用于一个通过Start()函数启动的模块,并且调用Start()之后不再需要调用任何成员函数的情况。

 

如果调用Start()之后,还需要调用一个叫做abc的函数呢?

 

如果这样使用没有错:

                                 

Test::GetInstance().Start(); 
Test::GetInstance().abc(); 

 正确

 

但是,恐怕,一般人会这样用:

 

Test test = Test::GetInstance();
test.Start();
test.abc(); 

 错误

 

错误在第一句,这是一个赋值操作,= 左面是一个对象, =右边是另一个对象, 右边的给左边的赋值,但是这是两个对象啊,test早已经不是那个单例的对象了。

 

总结: 你能保证模块的使用者肯定是上边的用法吗 ,如果不能保证,这种单例模式就不好。

 

第三种:

 

 这是第一种的改进, 第一种的缺陷是在第一次创建实例时有可能出错,我们可以避免这种情况:

 

在模块所在的.h文件中创建实例,只要用户包含了该头文件,实例就已经存在了,他再怎么创建也不是第一次了,代码如下

 

class Test
{
private:
    Test() {}
private:
    static Test* instance;
public:
    static Test* GetInstance()
    {
        if (!Test)
        {
            instance = new Test;
        }
        return instance;
    }
};

Test *ptest = Test::GetInstance();

 

 第四种:

 

照第三种这样的,也可以吧第二种改造一下喽,先创建对象,让用户用。

 

class Test
{
private:
    Test() {}
public:
    static Test& GetInstance()
    {
        static Test instance;
        return instance;
    }
};

#define sTest Test::GetInstance()

 

让用户用这个宏sTest当对象使用就行了,很不错。

 

到了这一步,就发现(13)和(24)这两种方式都差不多,都终都是在.h文件中首先实例化一个对象。

 

第五种:

 

  to be continue ... ....

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值