-
构造函数和静态成员私有
-
获取单例实例的静态方法公有
-
在实现文件中首先需对静态成员变量初始化为nullptr
-
随后main可通过静态方法获得单例实例
-
全局唯一实例: 单例模式的核心是确保一个类只有一个实例,并提供一个全局访问点。使用静态成员变量可以确保在整个程序生命周期内,只有一个实例存在。
-
静态成员变量的生命周期: 静态成员变量属于类而不是实例,它的生命周期与程序运行的整个周期相同。因此,一旦被初始化,就能一直存在,不会因为对象的创建和销毁而改变。
-
静态实例方法的访问点: 静态方法属于类而不是实例,可以在没有创建类实例的情况下调用。这是确保全局访问点的关键。静态方法通常用于创建或获取类的唯一实例。
-
#include <iostream>
class Singleton {
public:
// 获取单例实例的静态方法
static Singleton* getInstance() {
if (instance == nullptr) {
instance = new Singleton();
}
return instance;
}
// 示例成员函数
void showMessage() {
std::cout << "Hello from Singleton!" << std::endl;
}
private:
// 私有构造函数,防止直接实例化
Singleton() {}
// 静态成员变量,保存唯一实例
static Singleton* instance;
};
// 静态变量初始化
Singleton* Singleton::instance = nullptr;
int main() {
// 获取单例实例
Singleton* singleton1 = Singleton::getInstance();
singleton1->showMessage();
// 尝试再次获取实例,应该返回相同的实例
Singleton* singleton2 = Singleton::getInstance();
singleton2->showMessage();
// 检查两个指针是否相等,说明是同一个实例
if (singleton1 == singleton2) {
std::cout << "Same instance!" << std::endl;
} else {
std::cout << "Different instances!" << std::endl;
}
return 0;
}
Singleton
类有一个私有的静态成员变量 instance
,用于保存唯一的实例。通过静态方法 getInstance
获取实例,如果实例不存在,则创建一个新的实例;如果实例已经存在,则直接返回该实例
上述的简单实现在多线程环境下可能存在问题,因为多个线程同时调用 getInstance
可能导致创建多个实例。在实际应用中,可能需要使用线程安全的实现方式,例如使用互斥锁或者使用更为复杂的实现方式,如双重检查锁定
双重检查锁定(Double-Checked Locking)是一种用于在多线程环境下实现延迟初始化的设计模式。它的目标是在实现延迟初始化的同时,尽可能减小性能开销。
在单例模式中,延迟初始化是指在需要使用实例时才创建对象,而不是在程序启动时就创建。双重检查锁定是一种常见的实现方式,通常结合了懒汉式单例模式和锁定机制。
class Singleton {
public:
// 获取单例实例的静态方法
static Singleton* getInstance() {
// 双重检查锁定
if (instance == nullptr) {
std::lock_guard<std::mutex> lock(mutex); // 加锁
if (instance == nullptr) {
instance = new Singleton();
}
}
return instance;
}
// 示例成员函数
void showMessage() {
std::cout << "Hello from Singleton!" << std::endl;
}
private:
// 私有构造函数,防止直接实例化
Singleton() {}
// 静态成员变量,保存唯一实例
static Singleton* instance;
// 用于加锁的互斥量
static std::mutex mutex;
};