C++单例模式的实现
1. 饿汉式:
使用静态变量的线程安全性。
// 隐藏构造函数是因为防止主程序进行对象的构造
#define SINGLETON_CTOR(x) \
private:\
x() = default;\
x(const x&)=delete;\
x& operator=(const x&)=delete;\
~x()=default;
class SingletonStarve {
SINGLETON_CTOR(SingletonStarve);
public:
static SingletonStarve& instance() {
// 静态局部变量会在第一次使用时初始化,多次调用会被编译器忽略,生命周期是程序的运行区间。多线程安全
// 静态局部变量分配在全局静态数据区(不是堆和栈)
static SingletonStarve _instance;
return _instance;
}
};
int main() {
// 这里不可写成SingletonStarve singleton = SingletonStarve::instance(),因为会调用赋值函数执行拷贝初始化
SingletonStarve& singleton = SingletonStarve::instance();
}
2. 懒汉式
2.1 double-check
我们以double-check lock作为基本框架。为了处理此SingletonLazy单例的内存回收,我们使用unique_ptr来在程序结束时析构该对象。
class SingletonLazy {
SINGLETON_CTOR(SingletonLazy);
public:
static SingletonLazy& instance() {
// double check
if (p_instance == nullptr) {
std::lock_guard<std::mutex> lock(m_lock);
if (p_instance == nullptr) {
p_instance.reset(new SingletonLazy);
}
}
// 使用智能指针,建议返回引用
return *p_instance;
}
private:
static std::unique_ptr<SingletonLazy> p_instance;
static std::mutex m_lock;
};
// 记得初始化这俩静态变量
std::unique_ptr<SingletonLazy> SingletonLazy::p_instance;
std::mutex SingletonLazy::m_lock;
2.2 无锁——std::call_once
使用call_once来保护一段代码块(只执行一次)
class SingletonLazy {
SINGLETON_CTOR(SingletonLazy);
public:
static SingletonLazy& instance() {
static std::once_flag s_flag;
// 这段代码只会执行一次
std::call_once(s_flag, [&]() {
p_instance.reset(new SingletonLazy);
});
return *p_instance;
}
private:
static std::unique_ptr<SingletonLazy> p_instance;
};
std::unique_ptr<SingletonLazy> SingletonLazy::p_instance;
浙公网安备 33010602011771号