日常学习记录14:单例模式

单例模式是常考考点之一,盘一下。

1.单例模式

保证一个类仅有一个实例,提供一个全局访问点。

有饿汉式与懒汉式之分:
饿汉式:在初始化时就实例化
懒汉式:在第一次被引用时才实例化,即第一次调用getTest()时实例化

2.具体代码

总体而言的编码特征为:
私有:对象的指针、构造函数、[互斥锁]
公有:getTest()、[析构函数]
【注意:对象的指针、互斥锁、getTest均为static的】

具体实现主要有三种,本篇盘的均为懒汉式的:

(1)普通有缺陷的单例模式
在多线程场景下可能会多次new:例如线程1判断到t == nullptr,于是进去执行new,但是在线程1 new出来对象之前线程2判断到t == nullptr,于是也进去new。
没有析构函数的释放,造成内存泄漏。

//1.普通单例
class Test
{
private:
    static Test* t;
    Test()
    {
        cout<<"con"<<endl;
    }

public:
    static Test* getTest()
    {
        if(t == nullptr)
        {
            t = new Test();
        }
        return t;
    }
};

Test* Test::t = nullptr;//不要忘记初始化

(2)双重锁定的单例模式
使用双重锁定 + 互斥锁 + 智能指针解决(1)中的两个缺点

//2.双重锁定单例 智能指针+双重锁定+互斥锁
#include <mutex>
#include <memory>
class Test_2
{
private:
    static shared_ptr<Test_2> t;//注意
    static mutex mut;//注意
    Test_2()
    {
        cout<<"con_2"<<endl;
    }

public:
    ~Test_2()
    {
        cout<<"decon_2"<<endl;
    }

    static shared_ptr<Test_2> getTest()
    {
        if(t == nullptr)
        {
            lock_guard<mutex> lock(mut);
            if(t == nullptr)
            {
                t = shared_ptr<Test_2>(new Test_2);
            }
        }
        return t;
    }
};

shared_ptr<Test_2> Test_2::t = nullptr;
mutex Test_2::mut;

但是有些平台双重锁定(两个if)会失效,同时代码量也不小。

(3)局部静态变量的单例模式
此方法为最佳,即减少了代码量,又因为在初始化static变量时,并发进入声明语句会导致线程阻塞直到初始化结束,所以保证线程获取到的实例一定是初始化了的。

//3.局部静态变量
class Test_3
{
private:
    Test_3()
    {
        cout<<"con_3"<<endl;
    }

public:
    ~Test_3()
    {
        cout<<"decon_3"<<endl;
    }
    static Test_3& getTest()//注意返回值类型
    {
        static Test_3 t;
        return t;
    }
};

int main()
{
	Test& t = Test_3::getTest();//注意是引用类型
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值