c++单例模式包括懒汉模式和饿汉模式(优劣势分析和改进方法)

这篇具有很好参考价值的文章主要介绍了c++单例模式包括懒汉模式和饿汉模式(优劣势分析和改进方法)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1.单例模式说明

在整个软件的运行过程中,让整个类有且只有一个实例化对象存在于整个进程中。

是最简单的一个设计模式,然后再项目开发中也是使用最广的。

2.使用单例模式的优点

1.节省资源:再整个软件的运行过程中,只有一个实例化对象,不用重新分配新的堆空间。

2.数据的传递:由于单例只会创建一个实例化对象,比如有一个在停车场对你的车辆进行计费的程序。但是计费需要多个步骤,这样每个步骤调用的都是同一个单例,就能够记录每个步骤计算后的结果,知道算出正确结果为止。

3.单例模式实现分析

1.构造函数只能调用一次

如果已经有了实例化对象,就直接返回生成的实例化对象

如果没有就调用一次构造函数

2.具体实现,让构造函数只能被调用一次

把构造函数写到private:下面

删除拷贝构造函数和赋值符号构造函数

3.对象的生成不能依赖对象,所以要设置成静态的。

4.返回的创建的对象不能是类类型,因为这样会生成零时变量,因此返回类型要用指针或者引用

4.实际的应用场景

1.项目中的日志模块,一个项目只有一个日志的实例化对象

2.项目中的进程监控模块。

5.最基础的懒汉模式

#include <iostream>


using namespace std;

class Singleton {
private:
    static Singleton* m_pInstance;

private:
    Singleton() {
        cout << "constructor called!" << endl;
    }

    Singleton(Singleton&) = delete;
    Singleton& operator=(const Singleton&) = delete;

public:
    ~Singleton() {
        cout << "destructor called!" << endl;
    }

    static Singleton* getInstance() {
        if (m_pInstance == nullptr) {
            m_pInstance = new Singleton;
        }

        return m_pInstance;
    }
};

Singleton* Singleton::m_pInstance = nullptr;


int main()
{
    Singleton* instance1 = Singleton::getInstance();
    Singleton* instance2 = Singleton::getInstance();
    std::cout << "Hello World!\n";
}

c++单例模式包括懒汉模式和饿汉模式(优劣势分析和改进方法),设计模式,C++,c++,单例模式,开发语言

可以看到在main函数里面调用了两次getinstance,但是调用了一次构造函,说明达到了我们想要的效果

这个版本的懒汉模式还存在以下的缺陷

1.线程安全的问题:当多个线程同时获取单例的时候可能引发竞争的问题;当第一个线程

进入到 if (m_pInstance == nullptr),这个判断条件的时候,m_pInstance符合条件nullptr就会创建对应的实例化对象,与此同时,第二个线程也会进入到if (m_pInstance == nullptr)的判断。此时的m_pinstance也符合nullptr的条件,也会创建一个单例的实例化对象,此时就会有两个实例化对象,解决方法加锁

内存泄漏的问题:getInstance函数里面 ,new 了一个 类对象,但是没有进行释放,解决方法使用智能指针

6.线程安全,内存安全的懒汉模式(使用智能指针,加锁)

#include <iostream>
#include <mutex>

class Singleton {
public:
    using Ptr = std::shared_ptr<Singleton>;

    ~Singleton() {
        std::cout << "destructor called!" << std::endl;
    }

    Singleton(Singleton&) = delete;
    Singleton& operator=(const Singleton&) = delete;

    static Ptr getInstance() {
        if (m_pInstance == nullptr) {
            std::lock_guard<std::mutex> lk(m_mutex);

            if (m_pInstance == nullptr) {
                m_pInstance = std::shared_ptr<Singleton>(new Singleton);
            }
        }

        return m_pInstance;
    }

private:
    Singleton() {
        std::cout << "constructor called!" << std::endl;
    }

private:
    static Ptr m_pInstance;
    static std::mutex m_mutex;
};


Singleton::Ptr Singleton::m_pInstance = nullptr;
std::mutex Singleton::m_mutex;

int main() {
    Singleton::Ptr instance1 = Singleton::getInstance();
    Singleton::Ptr instance2 = Singleton::getInstance();

    return 0;
}

输出结果为

c++单例模式包括懒汉模式和饿汉模式(优劣势分析和改进方法),设计模式,C++,c++,单例模式,开发语言

程序对堆空间进行了释放,解决了内存安全的问题,

又使用了锁,解决了线程安全的问题。

缺陷:单例使用了智能指针,要求调用的用户也需要使用智能指针,

使用了锁也会增加相应的开销。理论上肯定是希望我们设计的程序越简单越好

7.最推荐的懒汉式单例(magic static )——局部静态变量

#include <iostream>
#include <mutex>

class Singleton
{
public:
    ~Singleton() {
        std::cout << "destructor called!" << std::endl;
    }

    Singleton(const Singleton&) = delete;
    Singleton& operator=(const Singleton&) = delete;

    static Singleton& getInstance() {
        static Singleton instance;
        return instance;
    }

private:
    Singleton() {
        std::cout << "constructor called!" << std::endl;
    }
};

int main(int argc, char* argv[])
{
    Singleton& instance_1 = Singleton::getInstance();
    Singleton& instance_2 = Singleton::getInstance();

    return 0;
}

这种方法又叫做 Meyers' SingletonMeyer's的单例, 是著名的写出《Effective C++》系列书籍的作者 Meyers 提出的。所用到的特性是在C++11标准中的Magic Static特性:

If control enters the declaration concurrently while the variable is being initialized, the concurrent execution shall wait for completion of the initialization.

如果当变量在初始化的时候,并发同时进入声明语句,并发线程将会阻塞等待初始化结束。

这样保证了并发线程在获取静态局部变量的时候一定是初始化过的,所以具有线程安全性。

C++静态变量的生存期 是从声明到程序结束,这也是一种懒汉式。

8.单例模式之饿汉式

饿汉模式 的区别就是,在程序调用单例之前提前生成实例化对象。

这样就不存在多线程竞争的问题。

#include <iostream>
#include <mutex>


class Singleton {
public:
    using Ptr = std::shared_ptr<Singleton>;
    static Ptr getInstance() {
        return m_pInstance;
    }

    ~Singleton() {
        std::cout << "destructor called!" << std::endl;
    }
private:
    static Ptr m_pInstance;
private:
    Singleton() {
        std::cout << "constructor called!" << std::endl;
    }
    Singleton(const Singleton&) = delete;
    Singleton& operator=(const Singleton&) = delete;
};
Singleton::Ptr Singleton::m_pInstance = std::shared_ptr<Singleton>(new Singleton);


int main(int argc, char* argv[])
{
    Singleton::Ptr instance1 = Singleton::getInstance();
    Singleton::Ptr instance2 = Singleton::getInstance();

    return 0;
}

9.单例模式之单例模板

#include <iostream>
#include <mutex>


//单例模板
template <typename T>
class Singleton {
private:
    Singleton() = default;
    ~Singleton() = default;
public:
    Singleton(const Singleton&) = delete;
    void operator = (const Singleton&) = delete;
   
    static T* instance()
    {
        static T m_instance;
        return &m_instance;
    }
};


class Student {
    public:
    Student() {
        std::cout << "constructor called!" << std::endl;
    }

    ~Student() {
        std::cout << "destructor called!" << std::endl;
    }
private:
    int num;
public:
    void setnum(int value) {
        num = value;
    }

    void getnum()
    {
        std::cout << num << std::endl;
    }
};


int main(int argc, char* argv[])
{
    Singleton<Student>::instance()->setnum(1);
    Singleton<Student>::instance()->getnum();
    Singleton<Student>::instance()->setnum(2);
    Singleton<Student>::instance()->getnum();
}

输出结果

c++单例模式包括懒汉模式和饿汉模式(优劣势分析和改进方法),设计模式,C++,c++,单例模式,开发语言

可以看到Student类调用了两次,但是只调用了一次构造函数,实现了我们想要的效果,其他的类也可以通过调用单列模板,达到这样类似的效果。

缺陷,不能阻止这样的声明出现 Student s; 在项目的其他地方声明这个类,也没问题。我们并没有禁止Student 类创建自己的对象

9.改善后的单例模板类

#include <iostream>
#include <mutex>


//单例模板
template <typename T>
class Singleton {
public:
    Singleton() = default;
    virtual ~Singleton() = default;
    Singleton(const Singleton&) = delete;
    void operator = (const Singleton&) = delete;

    static T* instance()
    {
        static T m_instance;
        return &m_instance;
    }
};



class Student:public Singleton<Student> {
    private:
    Student() {
        std::cout << "constructor called!" << std::endl;
    }

    ~Student() {
        std::cout << "destructor called!" << std::endl;
    }

    friend class Singleton<Student>;
private:
    int num;
public:
    void setnum(int value) {
        num = value;
    }

    void getnum()
    {
        std::cout << num << std::endl;
    }
};


int main(int argc, char* argv[])
{
    //Student stu;  报错 不可访问构造函数
    Student::instance()->setnum(1);
    Student::instance()->getnum();
    Student::instance()->setnum(2);
    Student::instance()->getnum();
}

输出结果

c++单例模式包括懒汉模式和饿汉模式(优劣势分析和改进方法),设计模式,C++,c++,单例模式,开发语言

本文只是做为一个总结,记录,实践作为自己学习用。参考了网上的很多其他文章。

主要参考了这篇C++ 单例模式-CSDN博客文章来源地址https://www.toymoban.com/news/detail-834184.html

到了这里,关于c++单例模式包括懒汉模式和饿汉模式(优劣势分析和改进方法)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

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

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

相关文章

  • Java设计模式之单例模式详解(懒汉式和饿汉式)

    在开发工作中,有些类只需要存在一个实例,这时就可以使用单例模式。Java中的单例模式是一种常见的设计模式,它确保一个类只有一个实例,并提供全局访问点。下面来介绍一下两种常见的单例模式:懒汉式和饿汉式。 懒汉式属于一种延迟加载的单例模式,它的特点是在

    2024年02月15日
    浏览(45)
  • 单例模式的饿汉和懒汉写法(基于C++)

    单例模式确保一个类只有一个实例,并提供全局访问点。这样可以避免在系统中出现多个相同的对象,从而提高系统的性能和可维护性。 单例模式的实现包括饿汉和懒汉,下面介绍C++中这两种方式的写法。 饿汉模式是在程序启动前创建实例。 下面是一个全局计数器的示例。

    2024年02月03日
    浏览(42)
  • 【单例模式】饿汉模式和懒汉模式的单例模式

    设计模式是一种 在软件设计中经过验证的解决问题的方案或者模版 。它们是从实践中总结出来的,可以帮助解决常见的设计问题,提高代码的重用性、维护性和扩展性。 设计模式可以分为三大类: 创建型模式(Creational Patterns) :创建型模式关注对象的实例化过程,包括如

    2024年02月16日
    浏览(68)
  • 设计模式之单例模式(懒汉, 饿汉)

    单例模式是一种常用的软件设计模式, 该模式的主要目的是确保某一个类在内存中只能有一个实例对象, 通过单例模式的方法创建的类在当前进程中只有一个实例对象. 常见的单例模式有两种: 饿汉式, 这里的 “饿” 意义表述不够清晰, 用 “急” 来表述意义更加容易联想一些

    2024年02月22日
    浏览(52)
  • 单例模式(饿汉式单例 VS 懒汉式单例)

    所谓的单例模式就是保证某个类在程序中只有一个对象 1.构造方法私有化(保证对象的产生个数)         创建类的对象,要通过构造方法产生对象        构造方法若是public权限,对于类的外部,可以随意创建对象,无法控制对象个数       构造方法私有化,这样类的外

    2024年02月09日
    浏览(42)
  • JavaEE:单例模式(饿汉模式和懒汉模式)精讲

    前言 什么是单例模式? 其实用通俗的话就是程序猿约定俗成的一些东西,就比如如果你继承了一个抽象类,你就要重写里面的抽象方法,如果你实现了一个接口,你就要重写里面的方法。如果不进行重写,那么编译器就会报错。这其实就是一个规范。 而单例模式能保证某个

    2024年02月04日
    浏览(49)
  • 自学设计模式(类图、设计原则、单例模式 - 饿汉/懒汉)

    设计模式需要用到面向对象的三大特性——封装、继承、多态(同名函数具有不同的状态) UML类图 eg.—— 描述类之间的关系(设计程序之间画类图)  +: public; #: protected; -: private; 下划线: static 属性名:类型(=默认值) 方法和变量分开------- 虚函数斜体,纯虚函数在虚函数类

    2024年02月11日
    浏览(41)
  • 懒汉单例设计模式与饿汉单例设计模式

    单例模式即一个类确保只有一个对象,主要用于避免浪费内存 1 .饿汉单例设计模式 :拿到对象时,对象就早已经创建好了 写法: 把类的构造器私有 在类中自己创建一个对象,并赋值到一个变量 定义一个静态方法,返回自己创建的这个对象 2. 懒汉单例设计模式 :第一次拿到对象时

    2024年02月21日
    浏览(59)
  • 单例模式类设计|什么是饿汉模式和懒汉模式

    那么这里博主先安利一些干货满满的专栏了! 首先是博主的高质量博客的汇总,这个专栏里面的博客,都是博主最最用心写的一部分,干货满满,希望对大家有帮助。 高质量干货博客汇总 https://blog.csdn.net/yu_cblog/category_12379430.html?spm=1001.2014.3001.5482 一个类只能创建一个对象,

    2024年02月16日
    浏览(44)
  • 24种设计模式之单例模式(饿汉式、懒汉式)

    单例模式( Singleton Pattern )是指确保一个类在任何情况下都绝对只有一个实例,并提供一个全局访问点。单例模式是创建型模式。单例模式在现实生活中应用也非常广泛,例如,总统,班主任等。J2EE标准中的ServletContext 、ServletContextConfig 等、Spring框架应用中的。 特点:构造方

    2024年02月07日
    浏览(48)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包