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对象。

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
单例模式是一种设计模式,它确保一个类只有一个实例,并提供一个全局访问点来获取该实例。在C++中,有多种实现单例模式的方式。 引用\[1\]中的代码演示了一种基于局部静态对象实现的单例模式。在这个例子中,Singleton类的构造函数和析构函数都是私有的,这样就禁止了用户自己声明和定义实例。通过getInstance()函数获取唯一的实例。这种实现方式具有线程安全性。 引用\[2\]中提到了C++实现单例的几种方式。其中,最推荐的是懒汉式单例(magic static)——局部静态变量。这种方式的代码简洁,没有智能指针调用和双重检查锁定模式的风险。 引用\[3\]中的代码展示了使用局部静态变量实现的懒汉式单例。SingletonPattern_V3类的构造函数和析构函数都是私有的,通过Instance()函数获取唯一的实例。 综上所述,C++中可以使用局部静态变量来实现单例模式,确保全局只有一个实例,并提供全局访问点。这种方式具有线程安全性,代码简洁。 #### 引用[.reference_title] - *1* [设计模式之单例模式(C++)](https://blog.csdn.net/zhaitianbao/article/details/128946441)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [C++ 单例模式](https://blog.csdn.net/u011718663/article/details/115922357)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值