饿汉
一个饥饿的人,看到食物就吃。
所以类加载了就创建了实例。
特点:
1.立即创建实例
2.线程安全
c
// 文件: main.cc
// 时间: 2024-07-26
// 来自: ccj
// 描述: 饿汉式单例
#include <iostream>
class Singleton {
public:
~Singleton() { std::cout << "~Singleton()" << std::endl; }
static Singleton& getInstance() { return instance; }
public:
void doSomething() { std::cout << "Doing something." << std::endl; }
private:
Singleton() { std::cout << "Singleton()" << std::endl; }
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;
private:
static Singleton instance;
};
// 立即创建实例
Singleton Singleton::instance;
int main() {
std::cout << "start use singleton" << std::endl;
Singleton& instance1 = Singleton::getInstance();
Singleton& instance2 = Singleton::getInstance();
// 验证是否为同一个实例
if (&instance1 == &instance2) {
std::cout << "instance1 and instance2 are the same instance." << std::endl;
}
instance1.doSomething();
instance2.doSomething();
return 0;
}

饱汉/懒汉
一个吃饱的人,食物可以放一会。
类先加载,在真正调用时创建实例
特点:
1.延时创建实例
2.加锁才能线程安全
3.每次获取单例会判断一次是否创建
4.要注意释放单例
c
// 文件: main.cc
// 时间: 2024-07-26
// 来自: ccj
// 描述: 饱汉式单例
#include <iostream>
#include <mutex>
class Singleton {
public:
~Singleton() { std::cout << "~Singleton()" << std::endl; }
static Singleton* getInstance() {
if (instance == nullptr) {
std::lock_guard<std::mutex> lock(mtx);
if (instance == nullptr) { instance = new Singleton(); }
}
return instance;
}
public:
void doSomething() { std::cout << "Doing something." << std::endl; }
private:
Singleton() { std::cout << "Singleton()" << std::endl; }
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;
private:
static Singleton* instance;
static std::mutex mtx;
};
// 先不创建实例
Singleton* Singleton::instance = nullptr;
std::mutex Singleton::mtx;
int main() {
std::cout << "start use singleton" << std::endl;
Singleton* instance1 = Singleton::getInstance();
Singleton* instance2 = Singleton::getInstance();
// 验证是否为同一个实例
if (instance1 == instance2)
std::cout << "instance1 and instance2 are the same instance." << std::endl;
instance1->doSomething();
instance2->doSomething();
// 注意: 需要自己释放
delete Singleton::getInstance();
return 0;
}

内部静态变量
C++11规定了local static在多线程条件下的初始化行为,要求编译器保证了内部静态变量的线程安全性。
特点:
1.延时创建实例
2.编译器保证线程安全
c
// 文件: main.cc
// 时间: 2024-07-26
// 来自: ccj
// 描述: 内部静态变量单例
#include <iostream>
class Singleton {
public:
~Singleton() { std::cout << "~Singleton()" << std::endl; }
static Singleton &getInstance() {
static Singleton s;
return s;
}
public:
void doSomething() { std::cout << "Doing something." << std::endl; }
private:
Singleton() { std::cout << "Singleton()" << std::endl; }
Singleton(const Singleton &) = delete;
Singleton &operator=(const Singleton &) = delete;
};
int main() {
std::cout << "start use singleton" << std::endl;
Singleton &instance1 = Singleton::getInstance();
Singleton &instance2 = Singleton::getInstance();
// 验证是否为同一个实例
if (&instance1 == &instance2)
std::cout << "instance1 and instance2 are the same instance." << std::endl;
instance1.doSomething();
instance2.doSomething();
return 0;
}

总结
尽可能用内部静态变量单例