[C++][特殊类设计][单例模式]详细讲解

目录

  • 1.[不能被拷贝]
  • 2.[只能在堆上创建对象]
  • 3.[只能在栈上创建对象]
  • 4.[请设计一个类,不能被继承]
  • 5.[只能创建一个对象(单例模式)]
    • 0. 设计模式
    • 1.单例模式
    • 2.饿汉模式
    • 3.懒汉模式
    • 4.单例对象释放问题

1.[不能被拷贝]

  • 拷贝只会发生在两个场景中:
    • 拷贝构造函数以及赋值运算符重载
    • 因此想要让一个类禁止拷贝, 只需让该类不能调用拷贝构造函数以及赋值运算符重载即可
  • C++98
    • 拷贝构造函数与赋值运算符重载只声明不定义,并且将其访问权限设置为私有即可
    • 原因:
      • **设置成私有:**如果只声明没有设置成private,用户自己如果在类外定义了,就不能禁止拷贝了
      • **只声明不定义:**不定义是因为该函数根本不会调用,定义了其实也没有什么意义,不写 反而还简单,而且如果定义了就不会防止成员函数内部拷贝了
class CopyBan
{// ...
private:CopyBan(const CopyBan &);CopyBan& operator=(const CopyBan&);//...
};
  • C++11
    • C++11扩展delete的用法,delete除了释放new申请的资源外,如果在默认成员函数后跟上 =delete,表示让编译器删除掉该默认成员函数
class CopyBan
{// ...CopyBan(const CopyBan&) = delete;CopyBan& operator=(const CopyBan&) = delete;//...
};

2.[只能在堆上创建对象]

  • 实现方式:
    1. 类的构造函数私有拷贝构造声明成私有。防止别人调用拷贝在栈上生成对象
    2. 提供一个静态的成员函数在该静态成员函数中完成堆对象的创建
class HeapOnly
{
public:// 提供一个公有的,获取对象的方式,对象则控制是new出来的static HeapOnly* CreateObject(){return new HeapOnly;}// 防拷贝HeapOnly(const HeapOnly& hp) = delete;HeapOnly& operator=(const HeapOnly& hp) = delete;
private:// 构造函数私有HeapOnly(){}
};

3.[只能在栈上创建对象]

  • **方法一:**同上将构造函数私有化,然后设计静态方法创建对象返回即可
class StackOnly
{
public:static StackOnly CreateObj(){return StackOnly();}// 不能防拷贝,若delete拷贝构造,则无法传值返回// 不好处理,算是一个小缺陷// 禁掉operator new可以把下面用new调用拷贝构造申请对象给禁掉// StackOnly obj = StackOnly::CreateObj();// StackOnly* ptr3 = new StackOnly(obj);void* operator new(size_t size) = delete;void operator delete(void* p) = delete;
private:StackOnly(){}
};

4.[请设计一个类,不能被继承]

  • C++98
// C++98中构造函数私有化,派生类中调不到基类的构造函数。则无法继承
class NonInherit
{
public:static NonInherit GetInstance(){return NonInherit();}
private:NonInherit(){}
};
  • C++11**:final关键字,final修饰类,表示该类不能被继承**
class A final
{// ....
};

5.[只能创建一个对象(单例模式)]

0. 设计模式

  • 设计模式(Design Pattern)是一套被反复使用、多数人知晓的、经过分类的、代码设计经验的总结
  • 使用设计模式的目的:
    • 为了代码可重用性、让代码更容易被他人理解、保证代码可靠性
    • 设计模式使代码编写真正工程化;设计模式是软件工程的基石脉络,如同大厦的结构一样

1.单例模式

  • 一个类只能创建一个对象,即单例模式,该模式可以保证系统中该类只有一个实例,并提供一个访问它的全局访问点,该实例被所有程序模块共享
    • 比如在某个服务器程序中,该服务器的配置信息存放在一个文件中,这些配置数据由一个单例对象统一读取,然后服务进程中的其他对象再通过这个单例对象获取这些配置信息,这种方式简化了在复杂环境下的配置管理
    • 单例模式有两种实现模式

2.饿汉模式

  • 饿汉模式 – 一开始(main函数之前)就创建出对象
  • 就是说不管你将来用不用,程序启动时就创建一个唯一的实例对象
  • 优点:
    • 简单、没有线程安全问题
    • 如果这个单例对象在多线程高并发环境下频繁使用,性能要求较高,那么显然使用饿汉模式来避免资源竞争,提高响应速度更好
  • 缺点:
    • 一个程序中,多个单例,并且有先后创建初始化顺序要求时,饿汉无法控制
    • 饿汉单例类,初始化时任务多,会影响程序启动速度
class Singleton
{
public:static Singleton* GetInstance(){return &_inst;}
private:// 构造函数私有Singleton(){};// C++11 -- 防拷贝Singleton(Singleton const&) = delete;Singleton& operator=(Singleton const&) = delete;static Singleton _inst; // 声明
};
Singleton Singleton::_inst; // 在程序入口之前就完成单例对象的初始化

3.懒汉模式

  • 如果单例对象构造十分耗时或者占用很多资源,比如加载插件, 初始化网络连接,读取文件等等,而有可能该对象程序运行时不会用到,那么也要在程序一开始就进行初始化, 就会导致程序启动时非常的缓慢
  • 所以这种情况使用**懒汉模式(延迟加载)**更好
  • 优点:
    • 控制顺序
    • 不影响启动速度
  • 缺点:
    • 相对复杂
    • 线程安全问题要处理好
class Singleton
{
public:static Singleton* GetInstance(){// 注意这里一定要使用Double-Check的方式加锁,才能保证效率和线程安全if (nullptr == _pinst){m_mtx.lock();if (nullptr == _pinst) // 第一次调用的时候才创建对象{_pinst = new Singleton();}m_mtx.unlock();}return _pinst;}// 实现一个内嵌垃圾回收类class CGarbo{public:~CGarbo(){if (Singleton::_pinst)delete Singleton::_pinst;}};// 定义一个静态成员变量,程序结束时,系统会自动调用它的析构函数从而释放单例对象static CGarbo Garbo;private:// 构造函数私有Singleton(){};// 防拷贝Singleton(Singleton const &);Singleton& operator=(Singleton const&);static Singleton* _pinst;      // 单例对象指针static mutex m_mtx;            // 互斥锁
};Singleton* Singleton::_pinst = nullptr;
Singleton::CGarbo Garbo;
mutex Singleton::m_mtx;

4.单例对象释放问题

  • 一般情况下,单例对象不需要释放的
    • 因为一般整个程序运行期间都可能会用它
    • 单例对象在进程正常结束后,也会资源释放
  • 有些特殊场景需要释放,比如单例对象析构时,要进行一些持久化(往文件、数据库写)操作

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/802141.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Google play开发者新手必看:2024最新最全的谷歌上架避坑指南

Google Play作为一个全球性的Android应用分发平台,吸引了无数开发者的目光。据统计,该平台的月活跃用户数已超过20亿,这无疑是一个巨大的市场。 但随着行业的发展,谷歌风控和审核机制不断升级,即便是经验丰富的开发者也…

Nginx配置文件修改结合内网穿透实现公网访问多个本地web站点

文章目录 1. 下载windows版Nginx2. 配置Nginx3. 测试局域网访问4. cpolar内网穿透5. 测试公网访问6. 配置固定二级子域名7. 测试访问公网固定二级子域名 1. 下载windows版Nginx 进入官方网站(http://nginx.org/en/download.html)下载windows版的nginx 下载好后解压进入nginx目…

抖音评论ID提取工具|视频关键词评论批量采集软件

抖音评论ID提取工具:批量抓取抖音评论 抖音评论ID提取工具是一款功能强大的软件,可以帮助您批量抓取抖音视频下的评论信息。通过输入关键词和评论监控词,即可进行评论的抓取,并提供评论昵称、评论日期、评论内容、命中关键词以及所…

C++更改文件名称,在文件名增加字符

void ChangeName(string filename) {char flagcharacter a; // 要在文件名前添加的标志字符int filelocation 0 ; // 暂存文件名起始下标int directoryend 0 ; // 暂存文件夹名结束下标for(int i (filename.length() - 1); i>0; i--)if(filenam…

嵌入式系统在智能家居与工业自动化等领域的应用创新

嵌入式系统在智能家居与工业自动化等领域的应用创新 随着科技的飞速发展,嵌入式系统已经渗透到我们生活的方方面面,特别是在智能家居和工业自动化领域,嵌入式系统的应用正带来前所未有的变革和创新。本文将深入探讨嵌入式系统在这两个领域的…

【CSDN活动】人工智能:前沿科技中的创业机遇与挑战

🌈个人主页: 鑫宝Code 🔥热门专栏: 闲话杂谈| 炫酷HTML | JavaScript基础 ​💫个人格言: "如无必要,勿增实体" 文章目录 人工智能:前沿科技中的创业机遇与挑战一、AI技术的快速发展与应用拓…

QML学习记录:并排页面切换效果的实现

定义一个ApplicationWindow窗口,通过添加SwipeView和PageIndicator来实现页面切换效果和显示当前页面位置的指示器。 ApplicationWindow {id:rootvisible: truewidth: 340height: 480title: qsTr("SwipeView") // 定义一个SwipeView用于页面切换效果 Swip…

Oracle ADG主备切换

文章目录 一、主库切换备库二、备库切换主库三、新备库(原主库)启用实时日志应用四、新主库切换日志五、查看当前主备库状态 一、主库切换备库 # 查看切换前的状态,确认当前从操作的是主库 select name,open_mode,switchover_status from v$…

Java每日一题

我的思路是: 通过示例我们可以判断出一共会有四种情况1.正常情况、2.负数、3.最后一位是0、4.反转后越界。 所以我就打算分为四步进行处理:首先我会创建两个StringBulider,一个用来存储原数字,一个用来存储结果集。 第一种情况进行处理的思路…

无人机倾斜摄影技术在智慧城市中的应用

随着智慧城市的不断发展和完善,新兴热门技术也不断崛起。无人机技术作为其中之一,具有操作简单、应用灵活等优势,受到了各个行业的青睐。现阶段,无人机技术与5G移动通信系统、人工智能系统深度融合,实现了无人机技术的…

LLMs之FreeGPT35:FreeGPT35的简介、安装和使用方法、案例应用之详细攻略

LLMs之FreeGPT35:FreeGPT35的简介、安装和使用方法、案例应用之详细攻略 目录 FreeGPT35的简介 FreeGPT35的安装和使用方法 1、部署和启动服务 Node 2、使用 Docker 部署服务: 运行 Docker 容器以部署服务 使用 Docker Compose 进行更方便的容器化…

抖音视频无水印采集软件|视频关键词批量提取工具

轻松实现抖音视频批量下载,让营销更高效! 随着抖音视频在营销领域的日益普及,如何高效地获取并管理大量视频资源成为了市场人员的重要挑战。针对这一需求,我们推出了一款强大的音视频无水印采集软件,帮助您轻松实现批量…

LeetCode刷题笔记第746题:使用最小花费爬楼梯

LeetCode刷题笔记第746题:使用最小花费爬楼梯 题目: 花费每个楼梯的代价就能向上爬一个或两个楼梯,求最终登顶需要的最小代价。 想法: 使用动态规划的思想将每个楼梯向上爬需要花费的最小代价记录下来,最终获得登顶…

C++笔记:学习使用C++

一.命名空间 namespace 名字 作用&#xff1a;一种用来隔离命名冲突的机制&#xff0c;是C的一项特性 例如&#xff1a; #include<iostream>namespace A {void func_1() {printf("hello world A\n");return ;} }namespace B {void func_1() {printf("hell…

MySQL——查询数据的处理

一、并列 连接两个数据列的值&#xff0c;并进行输出的格式化处理&#xff08;显示为一种统一的格式&#xff09; concat( 列 1 格式化字 符 ) mysql> select concat(vend_name, vend_country) from vendors; --------------------------------- | concat(vend_name, ve…

某211大学src挖掘

信息收集 这次信息收集比较玄学&#xff0c;起初就是用谷歌语法搜了一下带注册功能的点 然后就找到了本次目标站的注册点: 这边的学号啥的我都是不知道的而且这边最后显示的不是注册&#xff0c;显示的是提交所以可以断定注册账号得需要管理员审核信息才能注册&#xff0c;所以…

【Unity渲染】渲染管线原理

整理自B站UPKerry佬的视频【【教程】技术美术入门&#xff1a;渲染管线概述】 https://www.bilibili.com/video/BV1Q54y1G7v3/?share_sourcecopy_web&vd_source7e6249c05fba6efe32e8867373f75917 应用阶段 、几何阶段顶点处理、光栅化、片元处理、输出合并 应用阶段是CUP…

独家原创 | SCI 1区 高创新轴承故障诊断模型!

往期精彩内容&#xff1a; Python-凯斯西储大学&#xff08;CWRU&#xff09;轴承数据解读与分类处理 Python轴承故障诊断 (一)短时傅里叶变换STFT Python轴承故障诊断 (二)连续小波变换CWT_pyts 小波变换 故障-CSDN博客 Python轴承故障诊断 (三)经验模态分解EMD_轴承诊断 …

机器学习知识点

1鸢尾花分类 鸢尾花分类问题是一个经典的机器学习问题&#xff0c;旨在根据鸢尾花的花萼长度、花萼宽度、花瓣长度和花瓣宽度等特征&#xff0c;将鸢尾花分成三个品种&#xff1a;山鸢尾&#xff08;setosa&#xff09;、变色鸢尾&#xff08;versicolor&#xff09;和维吉尼亚…

【C++】——list的介绍及使用 模拟实现

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 目录 文章目录 前言 一、list的介绍及使用 1.1 list的介绍 1.2 list的使用 1.2.1 list的构造 1.2.2 list iterator的使用 1.2.3 list capacity 1.2.4 list element access 1.…