首页 > 编程语言 >【c++八股】手撕单例模式

【c++八股】手撕单例模式

时间:2024-03-06 15:58:35浏览次数:25  
标签:Singleton nullptr 八股 c++ instance static 单例 mutex delete

懒汉模式

class Singleton {
public:
    static Singleton& Instance() {
        if(instance_ == nullptr)
            instance_ = new Singleton();
        }
        return instance_;
    }

private:
    Singleton() {}
    ~Singleton() {}
	// 防拷贝
	Singleton(const Singleton& sing) = delete;
    Singleton& operator=(const Singleton& sing) = delete;
	
	static Singleton* instance_;
};
Singleton* Singleton::instance_ = nullptr;

懒汉模式-线程安全加锁

假如多个线程都调用了Instance方法,且都走到了判断为空那一步,可能同时成立。这样会导致多个线程同时创建instance_对象,即创建了多次,出现线程不安全的情况

使用lock_guard和mutex进行加锁:

class Singleton {
public:
    static Singleton* Instance() {
        //不需要每次都进来获取锁资源,提高效率
        if(instance_ == nullptr) {
            lock_guard<mutex> lk(mutex_);
            if(instance_ == nullptr) {
                instance_ = new Singleton();
            }
        }
        return instance_;
    }
    
private:
    Singleton() {}
    ~Singleton() {}
    Singleton(const Singleton& sing) = delete;
    Singleton& operator=(const Singleton& sing) = delete;
    static Singleton* instance_;
    static mutex mutex_;
};
Singleton* Singleton::instance_ = nullptr;
mutex Singleton::mutex_;

懒汉模式-内存泄漏优化

单例类中new出来的实例没有得到释放,所以需要方法来delete这个对象。

解决方法:(1)智能指针(2)嵌套类(3)C++11的静态对象特性

1 智能指针

利用shared_ptr的特性。

class Singleton {
public:
    static boost::shared_ptr<Singleton> Instance() {
        if(instance_ == nullptr) {
            lock_guard<mutex> lk(mutex_);
            if(instance_ == nullptr) {
                // 替换托管对象,并设置智能指针引用计数为0后的delete方法
                instance_.reset(new Singleton(), destroyInstance);
            }
        }
        return instance_;
    }
    static void destroyInstance(Singleton* instance) {
        delete instance;
    }
    
private:
    Singleton() {}
    ~Singleton() {}
    Singleton(const Singleton& sing) = delete;
    Singleton& operator=(const Singleton& sing) = delete;
    static boost::shared_ptr<Singleton> instance_;
    static mutex mutex_;

};
boost::shared_ptr<Singleton> Singleton::instance_ = nullptr;
mutex Singleton::mutex_;

2 嵌套类

在单例类中内嵌一个类,并初始化一个静态对象。当程序结束的时候,该对象进到析构的同时,将单例实例删除。这样就能回收单例实例的资源。

class Singleton {
public:
    static Singleton* Instance() {
        if(instance_ == nullptr) {
            lock_guard<mutex> lk(mutex_);
            if(instance == nullptr) {
                instance_ = new Singleton();
            }
        }
        return instance_;
    }
private:
    Singleton() {}
    ~Singleton() {}
    Singleton(const Singleton& sing) = delete;
    Singleton& operator=(const Singleton& sing) = delete;
    static Deletor deletor_;
    static Singleton* instance_;
    static mutex mutex_;
    
    class Deletor {
    public:
        Deletor() {}
        ~Deletor() {
            if(instance_ != nullptr) {
                delete instance_;
                instance_ = nullptr;
            }
        }
    }
};
Singleton::Deletor Singleton::deletor_;
Singleton* Singleton::instance_ = nullptr;
mutex Singleton::mutex_;

3 C++11的静态对象特性

C++11标准规定局部的静态对象在多线程场景下,只有初次访问才会被创建实例,后续都是直接获取。若未创建成功,其他线程就会等待,不会出现竞争的情况。而且资源会自动被销毁释放。

class Singleton {
public:
    static Singleton* Instance() {
        static Singleton* instance_;
        return instance_;
    }
private:
    Singleton() {}
    ~Singleton() {}
    Singleton(const Singleton& sing) = delete;
    Singleton* operator=(const Singleton& sing) = delete;
};

饿汉模式

程序启动阶段会初始化类的静态变量。

优点是不会有线程安全问题,缺点是浪费内存。

static对象在不同编译单元中的初始化顺序是未定义的。如果在初始化完成之前调用 Instance() 方法会返回一个未定义的实例。

class Singleton {
public:
    // 对外提供获取实例的静态方法
    static Singleton* Instance() {
        return instance_;
    }
private:
    // 私有构造函数
    Singleton() {}
    // 防拷贝
    Singleton(const Singleton& sing) = delete;
    Singleton& operator=(const Singleton& sing) = delete;
    
    static Singleton* instance_;
};

Singleton* Singleton::instance_ = new Singleton();

参考

https://blog.csdn.net/db_linux_driver/article/details/132548669

标签:Singleton,nullptr,八股,c++,instance,static,单例,mutex,delete
From: https://www.cnblogs.com/rthete/p/18056789

相关文章

  • C++的4种强制类型
    C++提供了4种强制类型转换的语法:静态转换(static_cast)static_cast是用于在没有二义性的前提下进行基本数据类型转换的一种转换方式。它只能用于具有相关性的数据类型之间的转换,如将int类型转换为double类型。如果进行无关的数据类型之间的转换,编译器将报错。用途:通常用......
  • C++ (3)
    3.函数1)函数声明中可以不写形参名而只写形参类型,这种函数声明成为函数原型。函数声明的位置可以在调用函数所在的函数中,也可以在函数之外。2)内置函数:编译时将所调用函数的代码直接嵌入到主调函数中,这种嵌入到主调函数中的函数称为内置函数(inlinefunction)。3)函数的重......
  • 店小密芒果店长商品搬家API接口PHP Java C++
    随着电子商务的迅猛发展,淘宝作为中国最大的电商平台之一,拥有着海量的商品数据和用户行为数据。为了更好地整合资源、提高运营效率,淘宝开放了商品详情API数据接口,为商家和第三方开发者提供了丰富的功能与应用。一、淘宝商品详情API数据接口概述淘宝商品详情API数据接口是淘宝开放......
  • C++ Qt开发:运用QThread多线程组件
    Qt是一个跨平台C++图形界面开发库,利用Qt可以快速开发跨平台窗体应用程序,在Qt中我们可以通过拖拽的方式将不同组件放到指定的位置,实现图形化开发极大的方便了开发效率,本章将重点介绍如何运用QThread组件实现多线程功能。多线程技术在程序开发中尤为常用,Qt框架中提供了QThread库来......
  • 01_C++基本数据类型_算数类型
    1.算数类型算数类型主要分为两类——整型和浮点型带符号和无符号类型带符号:int、short、long和longlong,通过在这些类型名前添加unsigned可以得到无符号类型。 选择符号的准则:(1)数值不可能为负时,选择无符号类型。(2)使用int执行整数运算。(3)算数表达式不要使用char或bool,存放字......
  • 【C++】判断一颗二叉树是否对称
    四步法:(1)如果两个子树都为空指针,则它们相等或对称(2)如果两个子树只有一个为空指针,则它们不相等或不对称(3)如果两个子树根节点的值不相等,则它们不相等或不对称(4)根据相等或对称要求,进行递归处理。//四步法判断一颗二叉树是否对称//主函数boolisSymmetric(TreeNode*root){......
  • 【C++】二叉树的前序、中序、后序遍历(递归、非递归)
    #include<vector>#include<iostream>#include<string>usingnamespacestd;//二叉树的定义structTreeNode{intval;TreeNode*left;TreeNode*right;TreeNode(inta):val(a),left(NULL),right(NULL){}};//使用递归进行前序遍历voidpreoder(Tr......
  • 【C++】求二叉树的最大深度和最小深度
    //求一颗二叉树的最大深度求高度:后序遍历求深度:前序遍历intmaxDepth(TreeNode*root){returnroot?1+max(maxDepth(root->left),maxDepth(root->right)):0;}//求一颗二叉树的最小深度(实质上是后序遍历)intminDepth(TreeNode*root){if(!root)retur......
  • 【C++】翻转二叉树(递归、非递归)
    //使用递归翻转二叉树TreeNode*reverseTree(TreeNode*root){if(!root)returnroot;swap(root->left,root->right);reverseTree(root->left);reverseTree(root->right);returnroot;}//使用队列翻转二叉树层序遍历TreeNode*invertTree(TreeNode*root)......
  • c++中nlohmann json的基本使用教程
    摘自:https://www.jb51.net/article/261677.htm 一.json.hpp库下载及安装1.1开源地址及引入方法nlohmannjson的开源项目地址,其中有对json使用方法的详细说明:https://github.com/nlohmann/json#serialization–deserialization对于我们项目中要使用nlohmannjson工具,只......