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;
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!