C++实现单例的5种方法总结
来源:互联网 发布:vb九九乘法表右上三角 编辑:程序博客网 时间:2024/06/16 15:54
本文结合一些已有的C++ 单例模式 设计方法,总结出了5种实现方式,并指出其中的使用特点和注意事项;
参考引用的文章链接:
++ 几种单例模式的写法
https://segmentfault.com/q/1010000004157283
一般情况下,为了实现单例我们都会想到使用 static 成员,下面#1是最基本的方式;
#1 静态指针成员:
class Singleton{ private: Singleton(){}; virtual ~Singleton(){}; public: Singleton *Instance(); protect: static Singleton *_instance; }; //Singleton.h Singleton *Singleton::instance() { if(NULL == _instance){ _instance = new Singleton(); } return _instance; } //Singleton.cpp
构造时机: 运行时生成;
对象位置: 堆
资源释放: new的单例对象,没有时机去释放;
线程安全: 否; ---在单例构造过程可能重复,造成内存泄露;
#2 静态指针成员(改进型):
在#1的基础上解决存在的两个问题;
如果单例对象的构造实在运行时之前(也就是程序静态变量初始化时完成)就可以避免线程安全的问题;
class Singleton{ public: static Singleton *instance(); private: Singleton(); virtual ~Singleton(); Singleton(const Singleton&){}; Singleton& operator=(const Singleton&){}; private: class CGarbo{ public: ~CGarbo() { if(Singleton::m_pInstance){ delete m_pInstance; } } }; private: static Singleton *m_pInstance; static CGarbo Garbo; }; //Singleton.h Singleton::CGarbo Singleton::Garbo; Singleton* Singleton::m_pInstance = new Singleton(); Singleton::Singleton() { printf("contructure funcation\n"); } Singleton::~Singleton() { printf("deconstructure funcation\n"); } Singleton* Singleton::instance() { return m_pInstance; } //Singleton.cpp
构造时机: 初始化时生成;
对象位置: 堆
资源释放: 通过一个成员的析构函数来释放单例对象,; 非常巧妙, 但是m_pInstance指针和 Garbo两个成员的析构是否有先后顺序,如果指针先被释放(指针变量变成NULL?)那么单例对象还是没有机会被释放; ---找时间确认一下,然后更新一下这个结果;
线程安全: 是; ---初始化过程,没有线程竞争;
对比以上两种方式,可以看出静态初始化的时候构造单例对象,能够比较好的解决线程安全的问题; 但是资源释放的需要通过曲线救国的方式来解决;
那么能不能把单例对象也生成在静态区呢?这样释放的问题就可以由操作系统自动完成;
#3 静态成员对象
class Singleton{ public: static Singleton *instance(); private: Singleton(); virtual ~Singleton(); Singleton(const Singleton&){}; Singleton& operator=(const Singleton&){}; private: static Singleton m_instance; }; //Singleton.h Singleton Singleton::m_instance; Singleton::Singleton() { printf("contructure funcation\n"); } Singleton::~Singleton() { printf("deconstructure funcation\n"); } Singleton *Singleton::instance() { return &m_instance; } //Singleton.cpp
构造时机: 初始化时生成;
对象位置: 静态区
资源释放: 在程序结束时 自动释放静态区的 成员变量
线程安全: 是;
注意: 静态成员的初始化需要放到类外完成; 那么是否可以把静态对象在成员函数instance()内部生成呢?
#4 静态局部对象
class Singleton{ public: static Singleton *instance(); private: Singleton(); virtual ~Singleton(); Singleton(const Singleton&){}; Singleton& operator=(const Singleton&){}; }; //Singleton.h Singleton::Singleton() { printf("contructure funcation\n"); } Singleton::~Singleton() { printf("deconstructure funcation\n"); } Singleton *Singleton::instance() { static Singleton ins; return &ins; } //Singleton.cpp
构造时机: 运行时生成; ---参考链接2 ; --对于C++的局部类对象,是在函数第一次调用时生成;
对象位置: 静态区
资源释放: 在程序结束时 自动释放静态区的 成员变量
线程安全: 是(C++11); ---参考链接2,, C++11标准针对局部静态对象的构造能保证线程安全(待查);
综合以上4中方式,单例对象的释放都是在程序结束时释放,
如果要求能够提供接口随时释放对象,那么就必须构造在堆上,然后提供显式的destroy接口;
#5 静态指针成员(动态释放)
#ifndef __MUTEX_H__ #define __MUTEX_h__ #include <pthread.h> class Mutex{ private: pthread_mutex_t m_mutex; public: Mutex(); virtual ~Mutex(); private: Mutex(const Mutex&){}; Mutex& operator=(const Mutex&){}; public: int lock(); int unlock(); int trylock(); }; #endif //__MUTEX_H__ //Mutex.h #include "Mutex.h" Mutex::Mutex() { pthread_mutex_init(&m_mutex, NULL); } Mutex::~Mutex() { pthread_mutex_destroy(&m_mutex); } int Mutex::lock() { return pthread_mutex_lock(&m_mutex); } int Mutex::unlock() { return pthread_mutex_unlock(&m_mutex); } int Mutex::trylock() { return pthread_mutex_trylock(&m_mutex); } //Mutex.cpp //单例类 #ifndef __SINGLETON_H__ #defile __SINGLETON_H__ #include "Mutex.h" class Singleton{ public: static Singleton *instance(); static void destroy(); private: Singleton(); virtual ~Singleton(); Singleton(const Singleton&){}; Singleton& operator=(const Singleton&){}; private: static Singleton *m_pInstance; static Mutex m_Mutex; }; #endif //__SINGLETON_H__ //Singleton.h Singleton* Singleton::m_pInstance = NULL; Mutex Singleton::m_Mutex; Singleton::Singleton() { //do something } Singleton::~Singleton() { //do something } Singleton* Singleton::instance() { if(NULL == m_pInstance){ m_Mutex.lock(); if(NULL == m_pInstance){ m_pInstance = new Singleton(); } m_Mutex.unlock(); } return m_pInstance; } void Singleton::destroy() { if(m_pInstance){ m_Mutex.lock(); if(m_pInstance){ delete m_pInstance; m_pInstance = NULL; } m_Mutex.unlock(); } } //Singleton.cpp
当然 也可以吧 静态成员指针放到接口函数里面作为局部静态变量 和局部静态对象;
- C++实现单例的5种方法总结
- Swift-总结单例实现的几种方法
- iOS单例模式的实现方法总结
- 单例模式c++实现方法总结
- 单例模式的5种实现方法。
- IOS实现单例模式的几种实现方法
- IOS实现单例模式的几种实现方法
- 单例模式的几种实现方式总结
- c实现的求质数几种方法总结
- 【Objective-C】单例模式的实现
- Objective-C 单例模式的实现
- C 语言单例的一种实现
- c++--Singleton单例模式的实现
- C++实现单例的几种方法
- JAVA单例模式的几种实现方法
- JAVA单例模式的几种实现方法
- JAVA单例模式的几种实现方法
- JAVA单例模式的几种实现方法
- xcode command line tool
- springsession使用redis
- +=隐式类型转换
- 初入职场-17加油!
- TextView相关属性
- C++实现单例的5种方法总结
- 设计模式:懒汉式和饿汉式
- MySQL分表处理的实现方法
- 一、2016年终总结
- 指针函数与函数指针示例
- ETL 自己的程序bug
- < meta > 元素 属性简介
- xcode配置问题
- [00316]结合时区的日期操作