C++之单例模式

news/2025/1/15 16:11:06/

文章目录

  • 什么是单例模式?
  • 单例模式中的饿汉模式
  • 单利模式中的懒汉模式

什么是单例模式?

保证一个类只有一个实例,并提供一个访问它的全局访问点,该实例被所有程序模块共享

单例模式中的饿汉模式

  • 饿汉模式:单例定义的时候就进行实力化(空间换时间的做法),不管需不需要用到实例都要去创建实例,在类产生的时候就创建好实例,体现了我全都要的特性
  • 在饿汉模式中,实例对象存储在全局数据区,所以用static修饰,是线程安全的,因为在线程创建之前实例就已经创建好了。

class Object
{
private:int value;static Object obja;
private:Object(int x = 0) :value(x) { cout << "Create Object" << endl; }Object(const Object&) = delete; //C++11Object& operator=(const Object&) = delete;
public:~Object() { cout << "Destory Object" << endl; }static Object& GetObj()  //不能以值返回,因为拷贝构造函数也被设置为私有的了{return obja;}/*static Object* GetObj(){return obja;} */void SetValue(int x) { value = x; }
};
Object Object:: obja(10);//Object* object::obj=new obja();
int main()
{Object& objecta = Object::GetObj(); //obja是全局变量,它的生命周期再局部函数结束时依然存在Object& objectb = Object::GetObj();objecta.SetValue(20);objectb.SetValue(10);
}

在这里插入图片描述

单利模式中的懒汉模式

  • 需要用到创建实例了才程序中创建实例,不需要创建实例程序就不去创建实例(时间换空间)
  • 定义一个静态类,使用类的私有静态指针变量指向类的唯一实例,并用一个公有的静态方法获取该实例
class Object
{
private:int value;static Object *pobja;//static int x;
private:Object(int x = 0) :value(x) { cout << "Create Object" << endl; }Object(const Object&) = delete; //C++11Object& operator=(const Object&) = delete;
public:~Object() { cout << "Destory Object" << endl; }static Object* GetObj()  //不能以值返回,因为拷贝构造函数也被设置为私有的了{if (nullptr == pobja){pobja = new Object(10);}return pobja;}void SetValue(int x) { value = x; }
};
Object* Object::pobja=nullptr;
//int Object::x = 10;
int main()
{Object* p = Object::GetObj();Object& objb = *Object::GetObj();p->SetValue(10);objb.SetValue(20);return 0;
}

在这里插入图片描述
但是懒汉模式存在的问题:
在单线程下可以,但是在多线程下会线程发生资源争夺,导致线程不安全,所以我们需要进行加锁操作

static Object* GetObj()  //不能以值返回,因为拷贝构造函数也被设置为私有的了{Lock();if (nullptr == pobja){pobja = new Object(10);}Unlock();return pobja;}

补充:这里我们将析构函数置位公有,当我们将析构函数也置位私有的时候,就会发现出现系统不会调用析构函数,这时出现了内存泄漏。
原因:在全局数据区的时候,存储的是一个实例对象的指针,真正的实例对象存放在堆区,我们需要手动释放资源,但也不能调用析构函数了

class Object
{
private:int value;static Object obja;
private:Object(int x = 0) :value(x) { cout << "Create Object" << endl; }Object(const Object&) = delete; //C++11Object& operator=(const Object&) = delete;
public:~Object() { cout << "Destory Object" << endl; }static Object& GetObj()  //不能以值返回,因为拷贝构造函数也被设置为私有的了{return obja;}static void deleteobj(){delete obja;}void SetValue(int x) { value = x; }
};
Object Object:: obja(10);//Object* object::obj=new obja();
int main()
{Object& objecta = Object::GetObj(); //obja是全局变量,它的生命周期再局部函数结束时依然存在Object& objectb = Object::GetObj();objecta.SetValue(20);objectb.SetValue(10);
}

http://www.ppmy.cn/news/63388.html

相关文章

聚观早报 | 菜鸟回应明年赴港 IPO;谷歌即将发布最新 AI 大模型

今日要闻&#xff1a;菜鸟回应明年赴港 IPO&#xff1b;谷歌即将发布最新 AI 大模型&#xff1b;中国移动推出周杰伦数字人&#xff1b;“老头乐”销量冠军雷丁汽车申请破产&#xff1b;网信部门工作组进驻斗鱼平台 菜鸟回应明年赴港 IPO 近日&#xff0c;有消息称&#xff0c…

华为OD题目: 取出尽量少的球

华为OD题目&#xff1a; 取出尽量少的球 时间限制: 1s 空间限制: 32MB 限定语言: 不限 题目描述: 某部门开展Family Day开放日活动&#xff0c;其中有个从桶里取球的游戏&#xff0c;游戏规则如下: 有N个容量一样的小桶等距排开&#xff0c;且每个小桶都默认装了数量不等的小…

C# Microsoft.ClearScript.V8脚本使用

1、ClearScript支持的功能和适用场景 微软的.net是非常强大和灵活的&#xff0c;除了C#体系脚本扩展&#xff0c;也支持其他流行的脚本扩展&#xff0c;Microsoft.ClearScript.V8就是一个.NET绑定到Google V8的脚本引擎。它允许.NET应用程序直接从JavaScript代码中调用函数&am…

linux下的Qt打包常见原因分析和雷区,获取一键式打包脚本(能避免各种问题)

目录 一. 大致如下常见问题&#xff1a; &#xff08;1&#xff09;找不到程序所依赖的Qt库 version Qt_5 not found (required by &#xff08;2&#xff09;Could not Load the Qt platform plugin "xcb" in "" even though it was found &#xff0…

单链表OJ题:LeetCode--206.反转链表

朋友们、伙计们&#xff0c;我们又见面了&#xff0c;今天给大家带来的是LeetCode中206题&#xff1a;反转链表 数 据 结 构&#xff1a;数据结构专栏 作 者&#xff1a;stackY、 C 语 言 &#xff1a;C语言专栏 LeetCode &#xff1a;LeetCode刷题训练营 LeetCod…

C++编译器对于对象的优化

C编译器对于对象构造的优化 用临时对象生成新对象时&#xff0c; 临时对象就不产生了&#xff0c;直接构造新对象即可 class Test { public:Test(int a 10) :ma(a){cout << "Test(int)" << endl;}~Test(){cout << "~Test()" <<…

常用的python gpu加速方法

在使用 PyCharm进行机器学习的时候&#xff0c;我们常常需要自己创建一些函数&#xff0c;这个过程中可能会浪费一些时间&#xff0c;在这里&#xff0c;我们为大家整理了一些常用的 Python加速方法&#xff0c;希望能给大家带来帮助。 在 Python中&#xff0c;我们经常需要创建…

springboot+vue校园宿舍管理系统

项目简介 分享一个SpringBootvue所做的一个项目&#xff0c;有需要的私信 1.项目描述 访问地址 http://localhost:8088/login.html?redirect_urlhttp://localhost:8087/myproject 超级管理员账户 账户名&#xff1a;admin 密码&#xff1a;123456 系统管理员账户 账户名…