单例模式
需要把构造函数私有化,这样就无法在类外创建实例。
| int main() {
Singleton obj; // 错误:Singleton的构造函数是私有的
}
|
但是可以 Singleton* Singleton::instance = new Singleton();,虽然构造函数是私有的,但它在Singleton
类内部是可访问的。
当你在类的成员函数或者静态成员初始化中调用这个构造函数时,你实际上仍然处于类的“内部”范围。这就是为什么new Singleton();是合法的。在这里,Singleton::instance
的初始化发生在类的“内部”,因此可以调用私有的构造函数。这与在类的外部尝试直接创建对象(如Singleton obj;
)是不同的
恶汉模式:
饿汉模式是指在程序启动时就创建单例对象,也就是将单例对象定义为静态成员变量,并在定义时直接初始化。实现饿汉模式的关键在于将构造函数声明为私有,这样就无法在类外创建实例。
缺点:饿汉模式的缺点在于无法控制单例对象的创建时间,可能会导致程序启动较慢
优点:线程安全
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 | class Singleton {
public:
static Singleton* getInstance() {
return instance;
}
private:
Singleton() {} // 将构造函数声明为私有
static Singleton* instance; // 定义为静态成员变量并直接初始化
};
Singleton* Singleton::instance = new Singleton(); // 直接初始化单例对象
int main() {
Singleton* obj1 = Singleton::getInstance();
Singleton* obj2 = Singleton::getInstance();
// obj1和obj2指向同一个单例对象
return 0;
}
|
懒汉模式:
懒汉模式是指在需要时才创建实例,也就是在第一次调用getInstance()方法时创建单例对象。实现懒汉模式的关键在于将构造函数声明为私有,这样就无法在类外创建实例,然后使用静态成员变量保存单例对象的指针,通过getInstance()方法返回该指针,实现对单例对象的访问。
缺点:线程不安全
优点:启动快
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 | class Singleton {
public:
static Singleton* getInstance() {
if (instance == nullptr) {
instance = new Singleton();
}
return instance;
}
private:
Singleton() {} // 将构造函数声明为私有
static Singleton* instance; // 静态成员变量保存单例对象的指针
};
Singleton* Singleton::instance = nullptr; // 初始化单例指针为nullptr
int main() {
Singleton* obj1 = Singleton::getInstance();
Singleton* obj2 = Singleton::getInstance();
// obj1和obj2指向同一个单例对象
return 0;
}
|
为了解决懒汉模式中的线程安全问题,我们可以使用双重锁定(DCL, Double-Checked Locking):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 | #include <mutex>
class Singleton {
public:
static Singleton* getInstance() {
if (instance == nullptr) {
std::lock_guard<std::mutex> lock(mtx);//std::lock_guar与mutex配合使用,把锁放到lock_guard中时,mutex自动上锁,lock_guard析构时,同时把mutex解锁
//也可以:
//mutex.lock();
if (instance == nullptr) {
instance = new Singleton();
}
//mutex.unlock();
}
return instance;
}
private:
Singleton() {}
static Singleton* instance;
static std::mutex mtx;
};
Singleton* Singleton::instance = nullptr;
std::mutex Singleton::mtx;
|