C++设计模式——单例模式
来源:互联网 发布:涡流分选器淘宝 编辑:程序博客网 时间:2024/06/14 01:23
C++设计模式——单例模式
概述
单例模式是一种常用的软件设计模式。在它的核心结构中只包含一个被称为单例的特殊类。通过单例模式可以保证系统中一个类只有一个实例。即一个类只有一个对象实例
单例模式的实现大概可以分为懒汉式实现和饿汉式实现。顾名思义,懒汉式就说明它很懒,只有在使用的时候才去创建对象。而饿汉式说明它很饿,还没开始使用就迫不及待的将对象创建出来了。
饿汉式实现
//Singleton.h#ifndef SIGLETON_H_#define SIGLETON_H_class Singleton{public: static Singleton* GetInstance(); //公有的获取对象的接口private: Singleton(){} //私有的构造函数 static Singleton* m_instance;};#endif
//Singleton.cpp#include "Singleton.h"Singleton* Singleton::m_instance = new Singleton();Singleton* Singleton::GetInstance(){ return m_instance;}
饿汉式实现的优缺点
优点
无须担心多线程的问题。
不需要加锁,执行效率比较高
缺点
- 在类刚加载的时候,就创建了该单例,消耗内存。
懒汉式实现
//Singleton.h#ifndef SIGLETON_H_#define SIGLETON_H_class Singleton{public: static Singleton* GetInstance();//公有的获取对象的接口private: Singleton(){} //私有的构造函数 static Singleton* m_instance;};#endif
//Singleton.cpp#include "Singleton.h"Singleton* Singleton::m_instance = NULL;Singleton* Singleton::GetInstance(){ if (NULL == m_instance) { m_instance = new Singleton(); } return m_instance;}
懒汉式实现优缺点
优点
- 不会在类刚加载的时候就初始化,能节省内存消耗
缺点
- 多线程不安全,必须要通过加锁来保证多线程安全,这样对运行效率有点影响。
懒汉式实现优化
使用加锁来实现懒汉式单例模式.
//Singleton.h#ifndef SIGLETON_H_#define SIGLETON_H_#include <iostream>#include <mutex> //C++11class Singleton{public: static Singleton* GetInstance();private: Singleton(){} //私有的构造函数 static Singleton* m_instance; static mutex m_mutex; //锁};#endif
//Singleton.cpp#include "Singleton.h"Singleton* Singleton::m_instance = NULL;mutex Singleton::m_mutex;Singleton* Singleton::GetInstance(){ if (NULL == m_instance) { std::lock_guard<std::mutex> lock(m_mutex); //在这儿上锁判断,只有多线程访问的时候才会执行上锁解锁,有效的缓解了加锁引起的效率问题。 if (NULL == m_instance) { m_instance = new Singleton(); } } return m_instance;}
内存释放问题
说了这么多,关于懒汉式单例模式创建之后的释放问题一直没有解决,我们在第一次初始化的时候创建出来,什么时候去释放它呢?提到这儿,懒汉式单例模式针对资源释放又衍生出了另外的四种实现方式。
1.局部静态变量返回引用实现
#ifndef SIGLETON_H_#define SIGLETON_H_#include <iostream>class Singleton{public: static Singleton& GetInstance() { static Singleton instance; //为了说明问题,忽略多线程。实际实现加锁和前面的懒汉式实现相同。 return instance; }private: Singleton(){} //私有的构造函数};
如此一来,对于单例的释放问题就很简单的解决了,但是如果代码中出现这样使用单例的:
Singleton instance = Singleton::GetInstance();
由于编译器在编译的时候,会自动生成拷贝构造函数,如果这样使用,会调用类的拷贝构造函数,从而制造出另外一个单例对象,这对于单例模式的初衷是矛盾的。因此,针对该问题,有了两种解决办法。
第一种解决办法,也就是懒汉式单例模式实现的第二种方法
2.局部静态变量返回指针实现
#ifndef SIGLETON_H_#define SIGLETON_H_#include <iostream>class Singleton{public: static Singleton* GetInstance() { static Singleton instance; //为了说明问题,忽略多线程。实际实现加锁和前面的懒汉式实现相同。 return &instance; }private: Singleton(){} //私有的构造函数};
这样就解决了调用默认拷贝构造函数引起的问题了。同时还有另外的一种实现,既然是编译器在发现类没实现的时候给默认添加了拷贝构造函数,那我们只需要把拷贝构造函数禁止掉就可以了。所以有了如下实现
3.局部静态变量返回引用,禁止拷贝构造函数实现
#ifndef SIGLETON_H_#define SIGLETON_H_#include <iostream>class Singleton{public: static Singleton& GetInstance() { static Singleton instance; //为了说明问题,忽略多线程。实际实现加锁和前面的懒汉式实现相同。 return instance; }private: Singleton(){} //私有的构造函数 Singleton(const Singleton&);//只声明,不实现 Singleton& operator = (const Singleton&);//只声明,不实现};
这样就有效的避免了在使用单例的时候,无意中调用了拷贝构造函数。当然还有一种高大上的自动释放的实现方式是使用GC机制。
4.使用GC机制的单例实现
class Singleton{public: static Singleton* GetInstance()private: class GC { public: ~GC() { if (Singleton::m_instance != NULL) { delete m_instance; m_instance = NULL; } } } static Singleton* m_instance; static GC gc;};
在使用的时候,必须要声明Singleton::GC:
Singleton::GC Singleton::GC::gc;//必须声明//...//do something//...
如此使用,当你程序结束的时候,就会调用调用GC的析构函数,GC的析构函数会将你的资源释放掉。实现自动释放的功能。
到这儿,五种创建型设计模式已经介绍完了:
1.简单工厂模式(不属于24种设计模式之一)
2.工厂方法模式
3.抽象工厂模式
4.建造者模式
5.原型模式
6.单例模式
- 设计模式——单例模式(c++)
- 设计模式——单例模式(C++)
- 设计模式—单例设计模式
- 设计模式——单例模式
- 设计模式——单例模式
- 设计模式——单例模式
- 设计模式——单例模式
- 设计模式——单例模式
- 设计模式——单例模式
- 设计模式——单例模式
- 设计模式——单例模式
- 设计模式——单例模式
- 设计模式——单例模式
- 设计模式——单例模式
- 设计模式——单例模式
- 设计模式——单例模式
- 设计模式——单例模式
- 设计模式——单例模式
- 主题模型-LDA浅析
- 如何尽快找到近期要召开的相关国际会议?
- LeetCode题解–134. Gas Station
- 在linux下使用sqlite
- USACO-Section1.4 Mother's Milk【广度优先搜索】
- C++设计模式——单例模式
- laravel文件上传
- java中常用的正则表达式
- 二分查找(折半查找)
- 腾讯视频和优酷视频怎么嵌入网页的方法
- PDOStatement::execute(): MySQL server has gone away
- spring的事务管理
- Django-admin
- frontEnd