【设计模式】C++单例模式详解

这篇具有很好参考价值的文章主要介绍了【设计模式】C++单例模式详解。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

单例模式

⼀个类仅有⼀个实例,并提供一个访问它的全局访问点,该实例被所有程序模块共享。

那么,我们必须保证:该类不能被复制;也不能被公开的创造。

对于 C++ 来说,它的构造函数,拷贝构造函数和赋值函数都不能被公开调用。

单例模式又分为 懒汉模式饿汉模式 ,它们之间各有好处:

  1. 懒汉模式的实例在第一次被引用时才进行初始化,支持延迟加载,资源利用效率更高;但是当资源访问频繁时,资源同步问题(加锁、解锁)会限制并发性能,也就是不支持高并发。

  2. 饿汉模式提前初始化实例,启动时间较长;但是可以避免资源同步(加锁、解锁)带来的性能消耗,后续的响应时间更好。

饿汉模式

在加载类时,对象实例就被创建并初始化,在程序结束时自动销毁,因此,它是线程安全的。

//.h文件 
class Singleton { 
public:   
    static Singleton* GetInstance(){    
        return _Instance; 
    }
  
private:   
    Singleton() = default;
    ~Singleton() = default;
    Singleton(const Singleton&) = delete;   
    Singleton& operator = (const Singleton&) = delete; 

private:   
    static Singleton* _Instance; 
}; 

// .CPP文件 
Singleton* Singleton::_Instance = nullptr;  // 类外初始化,必须写

懒汉模式

在 C++11 标准中,静态局部变量 的初始化是线程安全的,因此,可以用以下方式来编写“懒汉”模式:

class Singleton {
public:
    static Singleton& GetInstance() {
        static Singleton instance;  
        return instance;
    }
private:
    Singleton() = default;
    ~Singleton() = default;
    Singleton(const Singleton&) = delete;
    Singleton& operator = (const Singleton&) = delete;
};

更加传统的写法如下,使用 双重检查锁定 来确保线程安全,通过静态成员函数 Destructor 来解决内存泄漏:

//代码实例(线程安全) 
emplate<typename T> 
class Singleton { 
public: 
    static T* getInstance() {       
        if (_instance == nullptr) {   
            lock_guard<mutex> lock(_mutex);   
            if (_instance == nullptr) {     // 双重检查锁定, 确保线程安全
                _instance = new T();
                atexit(Destructor);     // 在程序退出的时候释放资源
            }
        }   
        return _instance; 
    } 
private:    
    // 防止外界构造/拷贝/删除对象
    Singleton() = default;     
    ~Singleton() = default;     
    Singleton(const Singleton&) = delete;
    Singleton& operator = (const Singleton&) = delete;
  
    static void Destructor() {
        if (_instance != nullptr) {
            delete _instance;
            _instance = nullptr;
        }
    }
    
    // 静态指针
    static T* _instance; 
    // 互斥锁
    static mutex _mutex;
}; 

// 初始化静态指针
template<typename T> 
T* Singleton<T>::_instance = nullptr;

// 初始化互斥锁
template<typename T>
mutex Singleton<T>::_mutex;

但是,这种写法可能出现以下问题:

由于 new 操作分为三步:分配内存、返回指针、调用构造函数;如果一个线程在分配内存后返回了指针,但还没有构造对象,另一个线程就尝试访问该对象的情况,就可能会出现未定义行为或错误。

因此,还是推荐使用“静态局部变量”的写法。

单例的应用

需要强调的是,单例只是一种组织全局变量和静态函数的方式

当我们想要拥有应用于某种全局数据集的功能,并且我们想要重复使用时,单例是非常有用的。比如以下场景:

  • 配置管理;

  • 日志记录;

  • 消息队列;

  • 线程池、连接池、内存池、对象池。

但是,单例模式是存在弊端的:

  1. 单例模式会隐藏类之间的依赖关系。

由于单例类不需要显示地创建,也不需要依赖参数传递,在函数中直接调用就好,所以在阅读代码时,需要仔细阅读才能清楚哪些类依赖了单例类。

  1. 单例模式的拓展性较差。

单例类只能创建一个实例,如果哪天需要在代码中创建多个实例,则需要对代码进行较大的改动。

以数据库连接池为例,假设一开始我们将其设计为一个单例类,而后我们发现,有些 SQL 语句的执行效率低下,长时间占用连接资源,因此我们希望再创建一个连接池实例,让它专门处理运行速度较慢的 SQL 语句,而此时,单例模式就对代码的拓展性产生了影响。文章来源地址https://www.toymoban.com/news/detail-744442.html

到了这里,关于【设计模式】C++单例模式详解的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 创建型模式 - 单例设计模式

    单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。 这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可

    2024年02月16日
    浏览(32)
  • 【设计模式 创建型】单例模式

    类的单例设计模式,就是 采取一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例 ,并且该类只提供一个取得其对象实例的方法(静态方法) 指一个类只有一个实例,且该类能自行创建这个实例的一种模式 。 特点: 某个类只能有一个实例( 即构造器私有

    2024年01月20日
    浏览(34)
  • 创建型设计模式06-单例模式

    🧑‍💻作者:猫十二懿 ❤️‍🔥账号:CSDN 、掘金 、个人博客 、Github 🎉公众号:猫十二懿 单例模式是一种创建型设计模式,它的目的是 确保一个类只有一个实例,并提供一个全局访问点来访问该实例 。在单例模式中,类自身负责创建自己的唯一实例,并确保在系统中只

    2024年02月08日
    浏览(33)
  • 学习笔记-设计模式-创建型模式-单例模式

    一个类只有一个实例,并提供一个全局访问此实例的点,哪怕多线程同时访问。 单例模式主要解决了 一个全局使用的类被频繁的创建和消费 的问题。 单例模式的案例场景 数据库的连接池不会反复创建 spring中一个单例模式bean的生成和使用 在我们平常的代码中需要设置全局

    2024年02月08日
    浏览(39)
  • 【地铁上的设计模式】--创建型模式:单例模式(五)--枚举单例

    什么是枚举单例 枚举单例是指使用枚举类型来实现单例模式,它是单例模式中最简单、最安全的一种实现方式。在枚举类型中定义的枚举值只会被实例化一次,即保证了全局唯一的实例,而且实现简单、线程安全、防止反射攻击、支持序列化等。 如何实现枚举单例 实现枚举

    2023年04月25日
    浏览(68)
  • 设计模式-创建型模式(单例、工厂、建造、原型)

    设计模式:软件设计中普遍存在(反复出现)的各种问题,所提出的解决方案。 面向对象三大特性:封装、继承、多态。 面向对象设计的SOLID原则: (1)开放封闭原则:一个软件实体如类、模块和函数应该对扩展开放,对修改关闭。即软件实体应尽量在不修改原有代码的情

    2024年02月08日
    浏览(43)
  • c#设计模式-创建型模式 之 单例模式

    目录 前言: 优点: 缺点: 饿汉式(静态变量方式) 懒汉式(线程不安全) 懒汉式(双重检查锁定) 推荐方式Lazy 总结: 这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供 了一种访问其唯一的对象的方式,可以直接访问,

    2024年02月13日
    浏览(27)
  • GO设计模式——4、单例模式(创建型)

    目录 单例模式(Singleton Pattern)   优缺点 使用场景 饿汉式和懒汉式单例模式         单例模式(Singleton Pattern)是一个类 只允许创建一个 对象(或者实例),那这个类就是一个单例类,这种设计模式就叫作单例设计模式,简称单例模式。单例模式的要点有三个:一是

    2024年02月05日
    浏览(36)
  • 深入理解设计模式-创建型之单例模式

    如果有些数据在系统中应该且只能保存一份,那就应该设计为单例类。 如:配置类:在系统中,我们只有一个配置文件,当配置文件被加载到内存之后,应该被映射为一个唯一的【配置实例】,此时就可以使用单例,当然也可以不用。 全局计数器:我们使用一个全局的计数

    2024年02月12日
    浏览(47)
  • 【Java 设计模式】创建型之单例模式

    在软件开发中,单例模式是一种常见的设计模式, 它确保一个类只有一个实例,并提供一个全局访问点 。单例模式在需要控制某些资源,如数据库连接池、线程池等共享资源的情况下非常有用。在本文中,我们将介绍 Java 设计模式中的单例模式,了解其实现方式、使用场景

    2024年01月18日
    浏览(46)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包