实际中存在这样的场景:对于系统中的某些类来说,确保只有一个实例很重要,例如,一个系统只能有一个窗口管理器或文件系统,软件的全局配置信息应该只有一份。单例模式确保一个类只有一个实例,并提供一个全局访问点。全局变量虽然可以确保对象随时都可以被访问,但不能防止我们实例化多个对象。这里介绍几种单例模式的C++实现:
懒汉模式
所谓懒汉模式就是第一次调用 getInstance()
时才产生对象,用到的时候才创建显得比较懒。
方法一: 使用局部静态变量,在C++0x之后才能保证 static 变量构造的线程安全性
class Singleton |
注意:这种方法在C++0x之前仍然需要加锁保护。这里将默认构造函数、拷贝构造函数和 operator= 都设为 private,防止在类作用域外的构造和赋值;而且拷贝构造函数和 operator= 都不实现,使得即使在友元类中也无法进行拷贝构造和赋值。
方法二:使用静态成员变量(指针),注意使用互斥锁并且 double-check
class Singleton |
注意:在类的作用域之外不能再使用 static 修饰其成员。该方法使用 RAII 封装的互斥锁 MutexLock,并使用 MutexLockGuard 栈上对象封装临界区。double-check 应对多个线程同时通过第一个 if 的情况。程序结束的时候,操作系统应该能够回收 new 申请的内存,也可以再利用 RAII 回收这部分内存(在 private 域添加如下代码即可):
class GarbageCollector() |
饿汉模式
相对于懒汉模式,饿汉模式是在类加载的时候就完成了单例对象的创建,像人饿了看到东西先吃了再说。
class Singleton |
注意:饿汉模式创建单例对象时不存在多线程 race condition,所以不用加锁保护。同样可以使用上面描述的 GarbageCollector 类回收内存。