首页 > 代码库 > 单例模式初探
单例模式初探
大致思路是,将该类的构造函数定义为私有方法,代码其他地方不能实例化该对象,只能通过调用该类的一个静态成员函数(get_instance())来获取这个唯一实例。
更进一步,把该类的复制构造函数和重载的=赋值运算也声明为私有,即Singleton(const Singleton)和 Singleton & operate = (const Singleton&)函数,需要声明成私有的,并且只声明不实现.
这里有个小坑是,当这个唯一的实例没有被创建时,有多个线程同时调用get_instance(),可能会造成过个实例的创建。因此需要牺牲一点效率做处理,如:加锁和双检测(double-check)以保护。
对于实例的创建,又有饿汉和懒汉两种模式,懒汉即在使用对象时才进行创建,如上面提到的,存在线程安全性问题。有一点补充的是,C++0X以后,要求编译器保证内部静态变量的线程安全性,可以不加锁。但C++ 0X以前,仍需要加锁。
而饿汉模式是,在进入主函数之前就由主线程以单线程方式完成了初始化,不必担心多线程问题,在性能需求较高时,应使用这种模式,避免频繁的锁争夺。但是多个单例模式的类相互引用时,由于静态成员变量 初始化顺序没有保障,会有坑出现,详见:
http://blog.csdn.net/crayondeng/article/details/24853471
以一个日志类为例:
考虑到日志文件只有一个的特点,我们用一个单例模式来实现,在其构造函数中完成对日志文件的初始化(打开和基本设置),其后每次读写操作只需拿到有效的文件句柄。
类的声明如下:
class Logger{ public: static Logger* get_instance(); int log_write(String &str, int errcode); int log_read(String &str, int errcode); static int mutex_init(); static pthread_mutex_t *mutex_for_creating; private: Logger(); ~Logger(); Logger(const Logger &); Logger & operator = (const Logger &); static Logger* p_logger; int fd; };
懒汉模式获取实例的函数大致如下:
static Logger* Logger::get_instance() { if (p_logger) return p_logger; pthread_mutex_lock(&mutex_for_creating); if (!p_logger) { p_logger = new Logger; } pthread_mutex_unlock(&mutex_for_creating); return p_logger; }
两个if语句即上面提到的双检测机制,确保线程安全。
进入程序前有两个初始化:
static Logger::p_logger = NULL; static int Logger::mutex_init() { if ((mutex_for_creating = new pthread_mutex_t) == NULL) return -1; pthread_mutex_init(&mutex_for_creating, NULL); return 0; }
而对于饿汉模式:
将实例的指针p_logger置为public,直接在进入主程序前new一个对象:
static Logger::p_logger = new Logger;
关于对象生命周期,一般可以不考虑,因为该对象通常是存在在整个程序的生命周期,随着程序的退出自动销毁。
而有些情况,如:“在类中,有一些文件锁了,文件句柄,数据库连接等等,这些随着程序的关闭而不会立即关闭的资源,必须要在程序关闭前,进行手动释放”[1]
也有一些参考的方法,如添加CGarbo类专门对单例对象进行回收,或者是用静态局部变量,如:http://blog.yangyubo.com/2009/06/04/best-cpp-singleton-pattern/和http://blog.csdn.net/Hackbuteer1/article/details/7460019
以及http://www.programlife.net/cpp-singleton-memory-retrieve.html
静态局部变量具有局部作用域,它只被初始化一次,自从第一次被初始化直到程序运行结束都一直存在,它和全局变量的区别在于全局变量对所有的函数都是可见的,而静态局部变量只对定义自己的函数体始终可见。
简单地说static 局部变量相对于局部变量:改变局部变量的存储位置,不改变局部变量的作用范围。
参考:[1] http://www.jellythink.com/archives/82
单例模式初探
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。