单例模式即保证一个类只有一个实例,并提供一个访问该单例的接口。
实例
1.懒汉式
用的时候才创建单例,“懒”。
Singleton.h
#ifndef SINGLETON_H_
#define SINGLETON_H_
#include <iostream>
#include <string>
#include <mutex>
class Singleton {
public:
static Singleton* GetInstance() {
if (instance_ == nullptr) {
// 加锁保证多个线程并发调用getInstance()时只会创建一个实例
m_mutex_.lock();
if (instance_ == nullptr) {
instance_ = new Singleton();
}
m_mutex_.unlock();
}
return instance_;
}
private:
Singleton() {}
static Singleton* instance_;
static std::mutex m_mutex_;
};
#endif // SINGLETON_H_
这就是双重检验锁,保障了线程安全。第一个判空可加速判断是否已有单例,第二个锁内的判空是为了解决多线程问题(两个线程同时走到lock,且instance_都为nullptr)。
Singleton.cpp
#include "Singleton.h"
// 静态变量instance初始化不要放在头文件中, 如果多个文件包含singleton.h会出现重复定义问题
Singleton* Singleton::instance_ = nullptr;
std::mutex Singleton::m_mutex_;
main.cpp
#include <iostream>
#include "Singleton.h"
int main() {
Singleton *s1 = Singleton::GetInstance();
Singleton *s2 = Singleton::GetInstance();
std::cout << "s1地址: " << s1 << std::endl;
std::cout << "s2地址: " << s2 << std::endl;
return 0;
}
编译运行:
$g++ -g main.cpp Singleton.cpp -std=c++11 -o singleton
$./singleton
s1地址: 0x95a040
s2地址: 0x95a040
2. 饿汉式
类初始化就创建单例,GetInstance()只是获取动作,“饿”。
Singleton.h
#ifndef SINGLETON_H_
#define SINGLETON_H_
class Singleton {
public:
static Singleton* GetInstance() {
return instance_;
}
private:
Singleton() {}
static Singleton* instance_;
};
#endif // SINGLETON_H_
Singleton.cpp
#include "Singleton.h"
Singleton* Singleton::instance_ = new Singleton();
main.cpp
#include <iostream>
#include "Singleton.h"
int main() {
Singleton *s1 = Singleton::GetInstance();
Singleton *s2 = Singleton::GetInstance();
std::cout << "s1地址: " << s1 << std::endl;
std::cout << "s2地址: " << s2 << std::endl;
return 0;
}
编译运行:
$g++ -g main.cpp Singleton.cpp -std=c++11 -o singleton
$./singleton
s1地址: 0x18a8040
s2地址: 0x18a8040
3. Meyers' Singleton
Meyers' Singleton是Scott Meyers提出的C++单例的推荐写法。它将单例对象作为局部static对象定义在函数内部:
#ifndef SINGLETON_H_
#define SINGLETON_H_
class Singleton {
public:
static Singleton& GetInstance() {
static Singleton instance;
return instance;
}
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;
private:
Singleton() {}
};
#endif // SINGLETON_H_
需要C11支持(C11保证static成员初始化的线程安全)