C++——单例模式

什么是单例模式?

** 单例模式其实就是设计一个类,确保只能实例化一个对象,并向系统提供这个函数**

单例模式有什么好处?

  • 在内存中只有一个对象,节省内存空间;
  • 避免频繁的创建销毁对象,可以提高系统性能;
  • 避免对共享资源的多重利用;
  • 可以全局访问

实现方法:

一、 因为只能有一个实例、所以将 构造函数、赋值运算符函数、拷贝构造函数写在私有下,禁止他人访问;如果不写在私有下,别人就能调用这三个函数来创建实例,无法实现单例模式。

二、那这样的话,我们设计的这个类就无意义了(因为在私有下啊,那创建的实例,系统获取不到啊,它又必须得给系统提供这个实例),那么为了使得类变得有意义我们可以在类中提供一个接口(static的getinstance公有函数)来获取到这个实例(静态私有对象)。****
接口特征

  • 不能依赖对象调用
  • 不能返回类类型(会有临时对象的生成)
#include<iostream>
#include<vector>
#include<string>
#inlcude<algorithm>
using namespace std;

class SingleTon
{
	private:
		int i;
		SingleTon (int x):i(x);  //构造函数: 不可访问
		void operaotr =(SingleTon &); //赋值操作函数: 不允许赋值运算
		SingleTon (const SingleTon &);  //拷贝构造函数:  不允许拷贝构造
	public:
		static SingleTon & instance()     //返回一个事例的引用; 类的对象
		{
			static SingleTon s(100);
			return s;
		}
		int getValue()  //取值
		{
			return i;
		}
		void setValue(int x)    //重新赋值
		{
			i=x;
		}
};

int main(void)
{
   SingleTon & s = SingleTon::instance();  //构造函数是私有类型,不可访问,故使用的是:引用
   cout<<s.getValue()<<endl;   //100
   
   SingkeTon & s2 = SingleTon::instance();  
   cout<<s2.getValue()<<endl; //100

   s2.setValue(20);
   cout<<s2.getValue()<<endl;  //20
   cout<<s.getValue()<<endl;   //20

   system("pause");
   return 0;
}  

单例模式一般根据实例化对象的时机不同分为这两类:

- 懒汉模式——延时加载

  • 第一次用到类实例的时候才会去实例化
  • 懒汉模式是线程不安全的,在并发的时候,会出现多个 SingleTon实例
  • 初始写法:
 class  SingleTon
 {
 	private:
 	    singleTon(){};    //私有构造函数
 	    static SingleTon *p; //单例对象
 	public:
 	    static SingleTon *GetInstance()
 	    {
 	    	if(p == nullpter)
 	    	{
 	    		p = new SingleTon();
 	    	}
 	    	return p;
 	    }
 }

这种实现方式是线程不安全的,为什么说不安全,请看:
在这里插入图片描述

  • 要实现线程安全,必须对getInstance 进进行改造,以确保安全
class SingleTon
{
    private:
    	SingleTon(){}   //私有构造方法
    	static Singleton *p;  //类定义声明
    public :
		//DCL 双重检测机制
      static Singleton* GetInstance()
    	{
    	 		if(p==nullptr)      //双重检测机制
    			{
    				lock();               //加同步锁
    				if(p==nullptr)    //双重检测机制
    				{
    					p= new Singleton();
    				}
    				unlock();
    		    }
        	    reutrn p;
          }
         //在getIntance中做了两次NULL检查,加了两次锁,确保了只有在第一次调用单例的时候才会做同步,这样也是线程安全的,同时避免了每次都同步的性能损耗问题。
         //进去临界区以后,还要做一次判空。因为当两个线程同时访问的时候,线程A构建完对象,线程B也已经通过了最初的判空验证,不做第二次判空的话,线程B仍然会再次构建instance对象。

如图看解析:为什么双重检测机制就保证线程安全了:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
- 饿汉模式——贪婪加载
饿汉、饥不择食,什么都吃,什么都要。所以不管用不用,他都要创建对象(即在类创建的时候就创建好实例)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值