单例类的两种形态
一、饿汉式
1.先上代码
#include <iostream>
#include <mutex>
//饿汉式
class HungryManExample
{
private:
//私有构造
HungryManExample() { };
private:
static HungryManExample* m_ptr;
public:
~HungryManExample() { };
static HungryManExample* getInstance();
void print()
{
std::cout << "HungryManExample--print" << std::endl;
}
};
//初始化---启动!!!
HungryManExample* HungryManExample::m_ptr = new HungryManExample;
HungryManExample* HungryManExample::getInstance()
{
return m_ptr;
}
int main()
{
HungryManExample::getInstance()->print();
delete HungryManExample::getInstance();
return 0;
}
2.结果
符合预期
3.开课啦
3.1 首先,构造函数需要时私有的,这是为了避免在HungryManExample类的作用域外,创建此类的对象。若是这样做,就不是单例类了。
3.2 其次,一个饥饿的男人是不会在运行时才做好准备的;饿汉不懒,他会在初始化时,做好准备,万事俱备,这样的饿汉谁不爱???
3.3 最后,饿汉启动,调用getInstance方法得到HungryManExample类对象的指针,去跑、去跳、去做一个漂亮的倒挂金钩。
二、懒汉式
1.先上代码
#include <iostream>
#include <mutex>
//懒汉式
class LazyManExample
{
private:
//私有构造
LazyManExample() { };
private:
static LazyManExample* m_ptr;
static std::mutex m_mutex;
public:
~LazyManExample() { };
//太懒了,就写在类里面当内联函数吧
static LazyManExample* getInstance()
{
//这个判断是为了不需要每次都进行锁定,提升性能
if(m_ptr == nullptr)
{
std::lock_guard<std::mutex> lock(m_mutex);
if(m_ptr == nullptr)//这个判断是为了多线程同时进入此函数时,不重复创建对象
{
m_ptr = new LazyManExample;
}
}
return m_ptr;
}
void print()
{
std::cout << "LazyManExample--print" << std::endl;
}
};
LazyManExample* LazyManExample::m_ptr = nullptr;
std::mutex LazyManExample::m_mutex;
int main()
{
LazyManExample::getInstance()->print();
delete LazyManExample::getInstance();//用完记得释放
return 0;
}
2.结果
符合预期
3.开课啦
3.1 首先,构造函数需要时私有的,这是为了避免在LazyManExample类的作用域外,创建此类的对象。若是这样做,就不是单例类了。
3.2 其次,一个懒惰的男人总是在火烧屁股时才动作,这个时候就可能会有多个线程同时找他,他就需要额外花费锁的开销进行处理。这样的懒汉,快介绍给你的闺蜜(认真且严肃)。
3.3 最后,催懒汉干活,调用getInstance方法得到LazyManExample类对象的指针,用完了别忘了擦干净,释放出去。
三、结语
无论是懒汉还是饿汉,总是有你爱的 和 合适的。最后你会和谁共度余生,就看你的选择了;如果你爱的正好爱着你,那该是有多幸运。但大多情况下,总是让人唏嘘不已。
在代码抽象的世界里,懒汉和恶汉也是如此的不好选择,有时,你偏爱饿汉,觉得他更单纯,也更上进,但经理偏要横插一脚,说你们不合适。大胆的追求爱吧,少年,毕竟,此时的你,要有:“大鹏一日同风起,扶摇直上九万里” 的理想和气概。