转自: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. sqli-labs less32-37(宽字节注入)

    less-32 Bypass addslashes() less-33 Bypass addslashes() less-34 Bypass Add SLASHES less-35 addslashe ...

  2. sqli-labs less11-12(post型union注入)

    less-11 post型union注入 过程: 输入admin admin 判断username password的闭合方式 对username查字段个数 ' union select 1,2# ' ...

  3. jmeter__编写脚本学习笔记、备忘

    web持续添加 前言: 1. token就是令牌,比如你授权(登录)一个程序时,他就是个依据,判断你是否已经授权该软件:也叫关联 2. cookie就是写在客户端的一个txt文件,里面包括你登录信息之 ...

  4. Mybatis学习-日志与分页

    日志 为什么需要日志 如果一个数据库操作出现了异常,需要排错,那么日志就是最好的助手 Mybatis通过使用内置的日志工厂提供日志功能,有一下几种实现方式: SLF4J Apache Commons ...

  5. 精尽Spring MVC源码分析 - HandlerMapping 组件(三)之 AbstractHandlerMethodMapping

    该系列文档是本人在学习 Spring MVC 的源码过程中总结下来的,可能对读者不太友好,请结合我的源码注释 Spring MVC 源码分析 GitHub 地址 进行阅读 Spring 版本:5.2. ...

  6. npm的下载与安装

    1.Node (1)什么是Node.js Node.js 就是运行在服务端的 JavaScript.Node.js 是一个基于Chrome JavaScript 运行时建立的一个平台. (2)Node ...

  7. Kali Linux破解wifi密码(无须外置网卡)

    环境准备:  方式一(选择该方式):Kali Linux.笔记本一台.U盘(至少8G)  方式二:Kali Linux.外置网卡.笔记本一台.VM   特别说明,主要是使用方式一进行破解,如果有外置网 ...

  8. Java可视化窗体

    加粗样式>Swing程序表示Java的客户端窗体程序,除了通过手动编写代码的方式设计Swing程序之外,Eclipse中还提供了一种WindowBuilder工具,该工具是一种非常好用的Swin ...

  9. C# 编译机器码过程原理之再谈反射

    一.引言 我们知道在Java中有虚拟机,代码运行时虚拟机把Java语言编译成与机器无关的字节码,然后再把字节码编译成机器指令执行,那么在.NET中程序是如何运行的呢? 其实运行原理是一样的,.NET中 ...

  10. Asp.net Core3.1+Vue 使用SignalR推送数据

    本文就简单使用 往前端页面推送消息 SignalR 是什么 SignalR是一个.NET Core/.NET Framework的开源实时框架. SignalR的可使用Web Socket, Serv ...