C++设计模式 - 单例模式(Singleton)
对象性能模式
面向对象很好地解决了"抽象”的问题,但是必不可免地要付出一定的代价。对于通常情况来讲,面向对象的成本大都可以忽略不计。但是某些情况,面向对象所带来的成本必须谨慎处理。
典型模式
- Flyweight
- Singleton
Singleton
单例模式其意图是:保证一个类只有一个实例,并提供一个访问它的全局访问点。
- 为了防止外部类构造实例,需要将构造函数的访问权限标记为protected或private;
- 需要提供全局访问点,就需要在类中定义一个static函数,返回在类内部唯一构造的实例。
线程非安全版本
#include <iostream>
class Singleton{
private:
Singleton(){
std::cout<<"constructor called!"<<std::endl;
}
Singleton(Singleton&)=delete;
Singleton& operator=(const Singleton&)=delete;
static Singleton* m_instance_ptr;
public:
~Singleton(){
std::cout<<"destructor called!"<<std::endl;
}
static Singleton* get_instance(){
if(m_instance_ptr==nullptr){
m_instance_ptr = new Singleton;
}
return m_instance_ptr;
}
void use() const { std::cout << "in use" << std::endl; }
};
Singleton* Singleton::m_instance_ptr = nullptr;
int main(){
Singleton* instance = Singleton::get_instance();
Singleton* instance_2 = Singleton::get_instance();
return 0;
}
线程安全版本,但锁的代价过高
#include <iostream>
#include <mutex>
class Singleton
{
private:
Singleton()
{
std::cout << "constructor called!" << std::endl;
}
Singleton(Singleton &) = delete;
Singleton &operator=(const Singleton &) = delete;
static Singleton *m_instance;
static std::mutex m_mtx;
public:
~Singleton()
{
std::cout << "destructor called!" << std::endl;
}
static Singleton *get_instance()
{
std::lock_guard<std::mutex> lk{m_mtx};
if (m_instance == nullptr)
{
m_instance = new Singleton();
}
return m_instance;
}
};
Singleton *Singleton::m_instance = nullptr;
std::mutex Singleton::m_mtx;
int main()
{
Singleton *instance = Singleton::get_instance();
Singleton *instance_2 = Singleton::get_instance();
return 0;
}
双检查锁,但由于内存读写reorder不安全
#include <iostream>
#include <mutex>
class Singleton
{
private:
Singleton()
{
std::cout << "constructor called!" << std::endl;
}
Singleton(Singleton &) = delete;
Singleton &operator=(const Singleton &) = delete;
static Singleton *m_instance;
static std::mutex m_mtx;
public:
~Singleton()
{
std::cout << "destructor called!" << std::endl;
}
static Singleton *get_instance()
{
if (m_instance == nullptr)
{
std::lock_guard<std::mutex> lk{m_mtx};
if (m_instance == nullptr)
{
m_instance = new Singleton();
}
}
return m_instance;
}
};
Singleton *Singleton::m_instance = nullptr;
std::mutex Singleton::m_mtx;
int main()
{
Singleton *instance = Singleton::get_instance();
Singleton *instance_2 = Singleton::get_instance();
return 0;
}
线程安全、内存安全的(智能指针,锁)
#include <iostream>
#include <memory>
#include <mutex>
class Singleton
{
public:
typedef std::shared_ptr<Singleton> Ptr;
~Singleton()
{
std::cout << "destructor called!" << std::endl;
}
Singleton(Singleton &) = delete;
Singleton &operator=(const Singleton &) = delete;
static Ptr get_instance()
{
if (m_instance_ptr == nullptr)
{
std::lock_guard<std::mutex> lk(m_mutex);
if (m_instance_ptr == nullptr)
{
m_instance_ptr = std::shared_ptr<Singleton>(new Singleton);
}
}
return m_instance_ptr;
}
private:
Singleton()
{
std::cout << "constructor called!" << std::endl;
}
static Ptr m_instance_ptr;
static std::mutex m_mutex;
};
Singleton::Ptr Singleton::m_instance_ptr = nullptr;
std::mutex Singleton::m_mutex;
int main()
{
Singleton::Ptr instance = Singleton::get_instance();
Singleton::Ptr instance2 = Singleton::get_instance();
return 0;
}
使用静态局部变量安全又高效
#include <iostream>
class Singleton
{
public:
~Singleton()
{
std::cout << "destructor called!" << std::endl;
}
Singleton(const Singleton &) = delete;
Singleton &operator=(const Singleton &) = delete;
static Singleton &get_instance()
{
static Singleton instance;
return instance;
}
private:
Singleton()
{
std::cout << "constructor called!" << std::endl;
}
};
int main(int argc, char *argv[])
{
Singleton &instance_1 = Singleton::get_instance();
Singleton &instance_2 = Singleton::get_instance();
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
2020-03-12 汇编语言-call和ret指令