首页技术文章正文

C++单例模式【黑马C++培训】

更新时间:2019年08月05日 10时10分23秒 来源:黑马程序员论坛

黑马中级程序员课程

单例模式是设计模式中最简单的形式之一。这一模式的目的是使得类的一个对象成为系统中的唯一实例。要实现这一点,可以从客户端对其进行实例化开始。因此需要用一种只允许生成对象类的唯一实例的机制,“阻止”所有想要生成对象的访问。使用工厂方法来限制实例化过程。这个方法应该是静态方法(类方法),因为让类的实例去生成另一个唯一实例毫无意义。<来自百度百科>

简单地说,单例模式表示的含义是某一个类, 在一个进程中只能有唯一的一个对象(实例), 并且在语法角度上进行制约.

单例模式要点
  • 某个类只能有一个实例

    • 单例模式的类只提供私有的构造函数,禁止使用拷贝构造函数或者赋值运算符来创建新的对象

  • 它必须自行创建这个实例

    • 类定义中,含有一个该类的静态私有对象,既保证所有的实例只有一个成员变量,那么等同于这个类只有一个对象

  • 他必须自行向整个系统提供这个实例

    • 该类提供一个静态的公有的函数用于创建或获取它本身的静态私有对象

单例模式用途

刚开始接触单例模式的时候,并不知道单例模式的用途是什么,但是其实使用单例模式的地方还是很多的,比如:

  • 每台计算机可以有若干个打印机,但只能有一个Printer Spooler, 以避免两个打印作业同时输出到打印机中。

  • 一个系统只能有一个窗口管理器或文件系统;

  • 一个系统只能有一个计时工具或ID(序号)生成器;

如在Windows中就只能打开一个任务管理器。如果不使用机制对窗口对象进行唯一化,将弹出多个窗口,如果这些窗口显示的内容完全一致,则是重复对象,浪费内存资源;如果这些窗口显示的内容不一致,则意味着在某一瞬间系统有多个状态,与实际不符,也会给用户带来误解,不知道哪一个才是真实的状态。因此有时确保系统中某个对象的唯一性即一个类只能有一个实例非常重要。

所以: 当实例存在多个会引起程序逻辑错误的时候,请使用单例模式

单例模式的优点
  • 单例模式会阻止其他对象实例化其自己的单例对象的副本,从而确保所有对象都访问唯一的实体

  • 因为类控制了实例化过程,所以类可以灵活更改实例化过程

单例模式缺点
  • 虽然数量很少,但是如果每次对象请求引用的时候都要检查是否存在类的实例,仍需要一些开销;

  • 懒汉模式以时间换空间;

  • 饿汉模式以空间换时间;

单例模式常见两种形式
  • 饿汉模式

饿汉模式就是一开始就将资源加再进来,可以说是一空间换时间的一种做法,每次使用的时候直接返回就好了

  • //饿汉模式
  • class Singleton
  • {
  • protected:
  •     Singleton(){} // 设置为保护便于被继承
  • private:
  •     Singleton(const Singleton& s) = delete; // 防拷贝(注:delete是c++11中的语法)
  •     Singleton* operator=(const Singleton& s) = delete; // 防赋值
  • private:
  •     static Singleton* p;
  • public:
  •     static Singleton* getInstance();
  • };
  • Singleton* Singleton::p = new Singleton(); // 第一次常见类就给分配资源
  • Singleton* Singleton::getInstance()
  • {
  •     return p;
  • }

注意: 饿汉模式不存在线程安全的问题

  • 懒汉模式

懒汉模式就是等到实例化对象的时候才将资源加载进来,可以说是以时间换空间的做法

经典懒汉模式(线程不安全)
  • class Singleton
  • {
  • protected:
  •     Singleton(){} //将构造函数设置为保护,便于其他类继承
  • private:
  •     Singleton(const Singleton& s) = delete; // 实现防拷贝
  •     Singleton& operator=(const Singleton& s) = delete; // 实现防赋值
  • public:
  •     static Singleton* getInstance();
  • private:
  •     static Singleton* p;
  • };
  • Singleton* Singleton::p = NULL;
  • Singleton* Singleton::getInstance()
  • {
  •     if(p == NULL)
  •     {// 在第一次调用的时候才去new一个对象
  •         p = new Singleton();
  •     }
  •     return p;
  • }
线程安全的懒汉模式
  • class Singleton
  • {
  • protected:
  •     Singleton()
  •     {// 初始化互斥锁
  •         pthread_mutex_init(&lock_,NULL);
  •     }
  • private:
  •     Singleton(const Singleton& s) = delete; // 实现防拷贝
  •     Singleton& operator=(const Singleton& s) = delete; // 实现防赋值
  • public:
  •     static pthread_mutex_t lock_;
  •     static Singleton* getInstance();
  • private:
  •     static Singleton* p; //加volatile防止编译器过度优化
  • };
  • pthread_mutex_t Singleton::lock_;
  • Singleton* Singleton::p = NULL;
  • Singleton* Singleton::getInstance()
  • {
  •     if(p == NULL)
  •     {
  •         pthread_mutex_lock(&lock_);
  •         if(p == NULL)
  •         {
  •             p = new Singleton();
  •         }
  •         pthread_mutex_unlock(&lock_);
  •     }
  •     return p;
  • }
内部静态变量实现懒汉模式
  • class Singleton
  • {
  • protected:
  •     Singleton()
  •     {
  •         pthread_mutex_init(&lock_,NULL);
  •     }
  • private:
  •     Singleton(const Singleton& s) = delete;
  •     Singleton* operator=(const Singleton& s) = delete;
  • public:
  •     static pthread_mutex_t lock_;
  •     static Singleton* getInstance();
  • };
  • pthread_mutex_t Singleton::lock_;
  • Singleton* Singleton::getInstance()
  • {
  •     pthread_mutex_lock(&lock_);
  •     static Singleton obj;
  •     pthread_mutex_unlock(&lock_);
  •     return &obj;
  • }
特点与选择
  • 由于要进行线程同步,所以在访问量比较大,或者可能访问的线程比较多时,采用饿汉实现,可以实现更好的性能。这是以空间换时间。

  • 在访问量较小时,采用懒汉实现。这是以时间换空间。

  • 面试的时候,就写饿汉模式吧,毕竟简单



推荐了解热门学科

java培训Python人工智能Web前端培训PHP培训
区块链培训影视制作培训C++培训产品经理培训
UI设计培训新媒体培训产品经理培训Linux运维
大数据培训智能机器人软件开发




传智播客是一家致力于培养高素质软件开发人才的科技公司“黑马程序员”是传智播客旗下高端IT教育品牌。自“黑马程序员”成立以来,教学研发团队一直致力于打造精品课程资源,不断在产、学、研3个层面创新自己的执教理念与教学方针,并集中“黑马程序员”的优势力量,针对性地出版了计算机系列教材50多册,制作教学视频数+套,发表各类技术文章数百篇。

传智播客从未停止思考

传智播客副总裁毕向东在2019IT培训行业变革大会提到,“传智播客意识到企业的用人需求已经从初级程序员升级到中高级程序员,具备多领域、多行业项目经验的人才成为企业用人的首选。”

中级程序员和初级程序员的差别在哪里?
项目经验。毕向东表示,“中级程序员和初级程序员最大的差别在于中级程序员比初级程序员多了三四年的工作经验,从而多出了更多的项目经验。“为此,传智播客研究院引进曾在知名IT企业如阿里、IBM就职的高级技术专家,集中研发面向中高级程序员的课程,用以满足企业用人需求,尽快补全IT行业所需的人才缺口。

何为中高级程序员课程?

传智播客进行了定义。中高级程序员课程,是在当前主流的初级程序员课程的基础上,增加多领域多行业的含金量项目,从技术的广度和深度上进行拓展“我们希望用5年的时间,打造上百个高含金量的项目,覆盖主流的32个行业。”传智播客课程研发总监于洋表示。




黑马程序员热门视频教程

Python入门教程完整版(懂中文就能学会)零起点打开Java世界的大门
C++| 匠心之作 从0到1入门学编程PHP|零基础入门开发者编程核心技术
Web前端入门教程_Web前端html+css+JavaScript软件测试入门到精通


在线咨询 我要报名
和我们在线交谈!