Singleton.h
/* * 确保一个类只有一个实例,并提供一个全局访问点 * * 应用 日志模块等 * * 优于全局变量的地方 * 1: 不污染全局名字空间 * 2: 保证一个类只有一个实例,定义一个全局变量也可以定义一个局部 */
class Singleton { public: static Singleton* instance(); // 只能通过这个函数来访问这个类的唯一实例
void fun(); // 用来演示的方法, 可以是写log等其他实际需要的函数
protected: Singleton(); // 构造函数是protected的,不能用Singleton来定义对象,保证只能通过instance函数得到一个Singleton对象保证了一个类一个实例
private: static Singleton *_instance; };
|
Singleton.cpp
#include "Singleton.h" #include <iostream> using namespace std;
Singleton* Singleton::_instance = NULL;
Singleton* Singleton::instance() { if(_instance == NULL) _instance = new Singleton; // 只在第一次执行
return _instance; }
Singleton::Singleton() { }
void Singleton::fun() { cout<<"Hello singleton"<<endl; }
|
main.cpp
#include "Singleton.h"
/* * 下面这一句不能用,否则报错,因为类的构造函数是protected的 * "main.cpp", line 8: Error: Singleton::Singleton() is not accessible from file level. * 这就保证了一个类只有一个实例 */ // Singleton noway;
int main() { Singleton::instance()->fun(); // 这里是使用Singleton的一个例子,在其他的类中都只要包含.h文件然后这么调用就可以了
return 0; }
|
上面的可以用于单线程,如果多线程,有可能多个线程同时看到指针为NULL,于是new新的对象,可能创建了多个对象,需要用到Double-Checked Locking避免这个问题。
加锁是针对instance函数
Singleton* Singleton::instance()
{
// A
if(_instance == NULL)
// B
_instance = new Singleton; // 只在第一次执行
return _instance;
}
如果在A点上锁,可行;但是每次调用都上锁,效率低。
如果在B点上锁,不可行;不能保证只有一个实例。
Double-Checked Locking方法
Singleton* Singleton::instance()
{
if(_instance == NULL)
{
// 在这加锁
if(_instance == NULL) // 第二次检查
_instance = new Singleton; // 只在第一次执行
}
return _instance;
}
由于加锁部分只执行一次或几次,之后不再执行,不影响效率。
总结
确保一个类只有一个实例,并且提供一个全局访问点。
一个静态类对象指针。
一个instance函数,第一次调用时new对象,并返回;不是第一次则直接返回已经创建的对象。
定义构造函数为protected或private,防止直接定义对象(只能用instance函数得到)。
多线程要结合Double-Checked Locking使用。
阅读(868) | 评论(0) | 转发(0) |