一 题目:实现单例模式Singleton

题目:设计一个类,我们只能生产该类的一个实例。

  只能生成一个实例的类是实现了Singleton(单例)模式的类型。由于设计模式在面向对象程序设计中起着举足轻重的作用,在面试过程中很多公司都喜欢问一些与设计模式相关的问题。在常用的模式中,Singleton是唯一一个能够用短短几十行代码完整实现的模式。因此,写一个Singleton的类型是一个很常见的面试题。

二:单例模式的几种实现方法

(1)单线程单例模式

  1. // 单例模式
  2. class Singleton
  3. {
  4. private:
  5. Singleton(){}
  6. ~Singleton(){delete m_pSingleton;};
  7.  
  8. public:
  9. static Singleton* Instance();
  10.  
  11. private:
  12. static Singleton*m_pSingleton;
  13. };
  14.  
  15. Singleton* Singleton::m_pSingleton = NULL;
  16. Singleton* Singleton::Instance()
  17. {
  18. if (!m_pSingleton)
  19. {
  20. m_pSingleton = new Singleton();
  21. }
  22.  
  23. return m_pSingleton;
  24. }

  这是一个很棒的实现,简单易懂。但这是一个完美的实现吗?不!该方法是线程不安全的,考虑两个线程同时首次调用instance方法且同时检测到p是NULL值,则两个线程会同时构造一个实例给p,这是严重的错误!同时,这也不是单例的唯一实现!

(2)懒汉单例模式

  a. 使用互斥对象实现懒汉模式

  1. // 单例模式
  2. class Singleton
  3. {
  4. private:
  5. Singleton(){};
  6. ~Singleton(){
  7. delete m_pSingleton;
  8. DeleteCriticalSection(&cs);}
  9.  
  10. public:
  11. static Singleton * Instance();
  12.  
  13. private:
  14. static Singleton *m_pSingleton;
  15. static CRITICAL_SECTION cs;
  16. static bool bInitCriticalSection;
  17. };
  18.  
  19. CRITICAL_SECTION Singleton::cs = {};
  20. bool Singleton::bInitCriticalSection = false;
  21. Singleton * Singleton::m_pSingleton = NULL;
  22.  
  23. Singleton * Singleton::Instance()
  24. {
  25. if (!bInitCriticalSection)
  26. {
  27. InitializeCriticalSection(&cs);
  28. bInitCriticalSection = true;
  29. }
  30. if (!m_pSingleton)
  31. {
  32. EnterCriticalSection(&cs);
  33. m_pSingleton = new Singleton();
  34. LeaveCriticalSection(&cs);
  35. }
  36.  
  37. return m_pSingleton;
  38. }

  b. 使用内部静态变量实现懒汉模式

  此方法也很容易实现,在instance函数里定义一个静态的实例,也可以保证拥有唯一实例,在返回时只需要返回其指针就可以了。推荐这种实现方法,真得非常简单

  1. // 单例模式
  2. class Singleton
  3. {
  4. private:
  5. Singleton(){}
  6. ~Singleton(){DeleteCriticalSection(&cs);}
  7.  
  8. public:
  9. static Singleton * Instance();
  10.  
  11. private:
  12. static CRITICAL_SECTION cs;
  13. static bool bInitCriticalSection;
  14. };
  15.  
  16. CRITICAL_SECTION Singleton::cs = {};
  17. bool Singleton::bInitCriticalSection = false;
  18. Singleton * Singleton::Instance()
  19. {
  20. if (!bInitCriticalSection)
  21. {
  22. InitializeCriticalSection(&cs);
  23. bInitCriticalSection = false;
  24. }
  25. EnterCriticalSection(&cs);
  26. static Singleton m_Singleton;
  27. LeaveCriticalSection(&cs);
  28.  
  29. return &m_Singleton;
  30. }

(3)饿汉单例模式

  饿汉实现本来就是线程安全的,不用加锁。为啥?自己想!

  1. // 单例模式
  2. class Singleton
  3. {
  4. private:
  5. Singleton(){};
  6. ~Singleton(){}
  7.  
  8. public:
  9. static Singleton * Instance();
  10.  
  11. private:
  12. static Singleton *m_pSingleton;
  13. };
  14.  
  15. Singleton * Singleton::m_pSingleton = new Singleton();
  16. Singleton * Singleton::Instance()
  17. {
  18. return m_pSingleton;
  19. }

剑指Offer面试题:1.实现单例模式的更多相关文章

  1. 剑指Offer:面试题15——链表中倒数第k个结点(java实现)

    问题描述 输入一个链表,输出该链表中倒数第k个结点.(尾结点是倒数第一个) 结点定义如下: public class ListNode { int val; ListNode next = null; ...

  2. 剑指offer面试题3 二维数组中的查找(c)

    剑指offer面试题三:

  3. 剑指Offer——笔试题+知识点总结

    剑指Offer--笔试题+知识点总结 情景回顾 时间:2016.9.23 12:00-14:00 19:00-21:00 地点:山东省网络环境智能计算技术重点实验室 事件:笔试 注意事项:要有大局观, ...

  4. C++版 - 剑指offer之面试题37:两个链表的第一个公共结点[LeetCode 160] 解题报告

    剑指offer之面试题37 两个链表的第一个公共结点 提交网址: http://www.nowcoder.com/practice/6ab1d9a29e88450685099d45c9e31e46?t ...

  5. C++版 - 剑指offer 面试题23:从上往下打印二叉树(二叉树的层次遍历BFS) 题解

    剑指offer  面试题23:从上往下打印二叉树 参与人数:4853  时间限制:1秒  空间限制:32768K 提交网址: http://www.nowcoder.com/practice/7fe2 ...

  6. C++版 - 剑指offer 面试题39:判断平衡二叉树(LeetCode 110. Balanced Binary Tree) 题解

    剑指offer 面试题39:判断平衡二叉树 提交网址:  http://www.nowcoder.com/practice/8b3b95850edb4115918ecebdf1b4d222?tpId= ...

  7. Leetcode - 剑指offer 面试题29:数组中出现次数超过一半的数字及其变形(腾讯2015秋招 编程题4)

    剑指offer 面试题29:数组中出现次数超过一半的数字 提交网址: http://www.nowcoder.com/practice/e8a1b01a2df14cb2b228b30ee6a92163 ...

  8. C++版 - 剑指Offer 面试题39:二叉树的深度(高度)(二叉树深度优先遍历dfs的应用) 题解

    剑指Offer 面试题39:二叉树的深度(高度) 题目:输入一棵二叉树的根结点,求该树的深度.从根结点到叶结点依次经过的结点(含根.叶结点)形成树的一条路径,最长路径的长度为树的深度.例如:输入二叉树 ...

  9. C++版 - 剑指offer 面试题24:二叉搜索树BST的后序遍历序列(的判断) 题解

    剑指offer 面试题24:二叉搜索树的后序遍历序列(的判断) 题目:输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果.如果是则返回true.否则返回false.假设输入的数组的任意两个 ...

  10. C++版 - 剑指Offer 面试题45:圆圈中最后剩下的数字(约瑟夫环问题,ZOJ 1088:System Overload类似)题解

    剑指Offer 面试题45:圆圈中最后剩下的数字(约瑟夫环问题) 原书题目:0, 1, - , n-1 这n个数字排成一个圈圈,从数字0开始每次从圆圏里删除第m个数字.求出这个圈圈里剩下的最后一个数字 ...

随机推荐

  1. samba 4.7.16 安装配置详解

    系统:Centos 7.4 x64位 服务版本:samba-4.7.1.samba-client-4.7 Samba 简介 Samba 是在Linux和UNIX系统上实现SMB协议的一个免费软件,由服 ...

  2. 一种BIM缺失多态性介导的酪氨酸激酶抑制剂的耐药性

    论文名称:A common BIM deletion polymorphism mediates intrinsic resistance and inferior responses to tyro ...

  3. 20145217《网络对抗》web基础

    20145217<网络对抗>web基础 一.问题 1.什么是表单? 表单:可以收集用户的信息和反馈意见,是网站管理者与浏览者之间沟通的桥梁. 表单包括两个部分:一部分是HTML源代码用于描 ...

  4. React Native之持久化存储(AsyncStorage、react-native-storage)的使用

    AsyncStorage是一个简单的.异步的.持久化的Key-Value存储系统,它对于App来说是全局性的.这是官网上对它的介绍.可以知道,这个asyncstorage也是以键值对的形式进行存储数据 ...

  5. 《大型网站系统与JAVA中间件实践》读书笔记-数据访问层

    数据访问层 5.1.2数据库垂直/水平拆分的困难 随着网站业务的快速发展,数据量和访问量不断上升,数据库的压力越来越大. 更换更好的硬件(Scale Up)是一种解决方案,而且在我们能付得起硬件费用并 ...

  6. 谈谈RMQ问题

    没用的话:好像好久没更博了,无聊就讲讲算法吧(主要找不到水题). 感觉针对初学者,老师教这个算法时没怎么懂,最近(大概1.2个月前吧)老师又教了lca(最近公共祖先,额,可以百度,我就不讲了,可能以后 ...

  7. hibernate配置文件的详解

    <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE hibernate-configurati ...

  8. Java IO操作——数据操作流DataOutputStream和DataInputStream的使用

    学习目标  掌握DataOutputStream和DataInputStream的作用 可以使用DataOutputStream和DataInputStream写入和读入数据 数据操作流 在io包中, ...

  9. Three.js基础:导入STL模型文件

    stlloadertest.html: <!DOCTYPE html> <html lang="en"> <head> <title> ...

  10. vue2 遇到的问题汇集ing

    1 .子路由 { path: '/order-list', //订单列表 name: "order-list", component(resolve) { require.ensu ...