转自:https://blog.csdn.net/liang19890820/article/details/61615495

Singleton 的头文件(懒汉式/饿汉式公用):

// singleton.h
#ifndef SINGLETON_H
#define SINGLETON_H #include <iostream>
#include <mutex>
using namespace std; // 单例 - 懒汉式/饿汉式公用
class Singleton
{
public:
static Singleton* GetInstance();
static void DestoryInstance()//手动释放资源
{
if (m_pSingleton != NULL) {
delete m_pSingleton;
m_pSingleton = NULL;
}
}
private:
Singleton() {} // 构造函数(被保护) private:
static Singleton *m_pSingleton; // 指向单例对象的指针
static mutex m_mutex; // 锁
}; #endif // SINGLETON_H

懒汉式

懒汉式的特点:

  • Lazy 初始化
  • 非多线程安全

优点:第一次调用才初始化,避免内存浪费。 
缺点:必须加锁(在“线程安全”部分分享如何加锁)才能保证单例,但加锁会影响效率。

在懒汉式下,如果使用多线程,会出现线程安全隐患。为了解决这个问题,可以引入双检锁 - DCL 机制。

// singleton.cpp
#include "singleton.h" // 单例 - 懒汉式(双检锁 DCL 机制)
Singleton *Singleton::m_pSingleton = NULL;
mutex Singleton::m_mutex; Singleton *Singleton::GetInstance()
{
if (m_pSingleton == NULL) {
std::lock_guard<std::mutex> lock(m_mutex); // 自解锁
if (m_pSingleton == NULL) {
m_pSingleton = new Singleton();
}
}
return m_pSingleton;
}

饿汉式

饿汉式的特点:

  • 非 Lazy 初始化
  • 多线程安全

优点:没有加锁,执行效率会提高。 
缺点:类加载时就初始化,浪费内存。

// singleton.cpp
#include "singleton.h" // 单例 - 饿汉式
Singleton *Singleton::m_pSingleton = new Singleton(); Singleton *Singleton::GetInstance()
{
return m_pSingleton;
}

面试比较好的解法:

// singleton.h
#ifndef SINGLETON_H
#define SINGLETON_H #include <iostream> using namespace std; // 单例 - 自动释放
class Singleton
{
public:
static Singleton* GetInstance(); private:
Singleton() {} // 构造函数(被保护) private:
static Singleton *m_pSingleton; // 指向单例对象的指针 // GC 机制
class GC
{
public:
~GC()
{
// 可以在这里销毁所有的资源,例如:db 连接、文件句柄等
if (m_pSingleton != NULL) {
cout << "Here destroy the m_pSingleton..." << endl;
delete m_pSingleton;
m_pSingleton = NULL;
}
}
static GC gc; // 用于释放单例
};
}; #endif // SINGLETON_H
// main.cpp
#include "singleton.h" Singleton::GC Singleton::GC::gc; // 重要 int main()
{
Singleton *pSingleton1 = Singleton::GetInstance();
Singleton *pSingleton2 = Singleton::GetInstance(); cout << (pSingleton1 == pSingleton2) << endl; return 0;
}

剑指offer 面试题2:实现Singleton模式的更多相关文章

  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. 【APIO2019】路灯(ODT & (树套树 | CDQ分治))

    Description 一条 \(n\) 条边,\(n+1\) 个点的链,边有黑有白.若结点 \(a\) 可以到达 \(b\),需要满足 \(a\to b\) 的路径上的边不能有黑的.现给出 \(0\ ...

  2. 笔记-CF643E Bear and Destroying Subtrees

    CF643E Bear and Destroying Subtrees 设 \(f_{i,j}\) 表示节点 \(i\) 的子树深度为 \(\le j\) 的概率,\(ch_i\) 表示 \(i\) ...

  3. 你必须要知道的HTTP协议原理

    1 基本概念 HTTP协议:基于TCP协议之上实现的无状态.全文本的标准通信协议. 客户端:例如pc浏览器,移动应用端,第三方服务器等能发起http访问的设备. 服务器:能够接受HTTP协议请求,并且 ...

  4. 超详细!使用 LVS 实现负载均衡原理及安装配置详解---转

    负载均衡集群是 load balance 集群的简写,翻译成中文就是负载均衡集群.常用的负载均衡开源软件有nginx.lvs.haproxy,商业的硬件负载均衡设备F5.Netscale.这里主要是学 ...

  5. js实现弹幕

    弹幕是一个很常见的功能,下面是本人封装的一个小小的实现方案,存在不足之处可以提出来或自由改进. 直接上代码:复制可运行 <!DOCTYPE html> <html> <h ...

  6. 【jenkins】构建工作集

    构建工作集,参数化工作任务 1.New Item 2.配置新的工作任务 3.关联测试用例的远程仓库 4.添加任务构建后,触发发送报告信息 5.新建单个测试套件 6.添加触发轮询任务 7.关联测试集 8 ...

  7. Asp.net core验证类ModelStateDictionary的bug

    在使用.net core 3.1 时发现明明没有验证请求类属性,甚至已经加了默认值 但是验证类时依然会报错 经过网上百度等搜索,尝试使用可空类型赋值默认值 果然验证类没有报错 不清楚是微软的bug还是 ...

  8. Springboot之登录模块探索(含Token,验证码,网络安全等知识)

    简介 登录模块很简单,前端发送账号密码的表单,后端接收验证后即可~ 淦!可是我想多了,于是有了以下几个问题(里面还包含网络安全问题): 1.登录时的验证码 2.自动登录的实现 3.怎么维护前后端登录状 ...

  9. Hadoop核心-HDFS

    上一篇我们熟悉了hadoop,本篇讲解一下hadoop第一个核心HDFS. 一.概述 HDFS是一个分布式文件存储系统,以流式数据访问模式存储超大文件,将数据分块存储到一个商业硬件集群内的不同机器上, ...

  10. Spark内核-部署模式

    Master URL Meaning local 在本地运行,只有一个工作进程,无并行计算能力. local[K] 在本地运行,有K个工作进程,通常设置K为机器的CPU核心数量. local[*] 在 ...