单例模式的作用:
1). 确保一个类只有一个实例被建立
2). 提供了一个对对象的全局访问指针
3). 在不影响单例类的客户端的情况下允许将来有多个实例
1.懒汉式
懒汉式的特点是延迟加载:
class Singleton
{
public:
~Singleton() = default;
static Singleton* GetInstance()
{
if (nullptr == m_pInstance)
{
m_pInstance = make_shared<Singleton>();
}
return m_pInstance.get();
}
private:
Singleton() = default;
static shared_ptr<Singleton> m_pInstance;
};
2.饿汉式
饿汉式的特点是一开始就加载了:
class Singleton
{
public:
~Singleton()
{
cout<<"singleton destructor"<<endl;
}
static Singleton* GetInstance()
{
static Singleton instance;
return &instance;
}
private:
Singleton()
{
cout<<"singleton constructor"<<endl;
}
};
饿汉式是线程安全的,在类创建的同时就已经创建好一个静态的对象供系统使用;而懒汉式不是线程安全的。下面是多线程下的单例模式。
3.多线程下的单例模式
这里要处理的是懒汉模式。
class Singleton
{
private:
mutex mtx_;
Singleton() = default;
static shared_ptr<Singleton> m_pInstance;
public:
static Singleton* GetInstance()
{
if (lock_guard<mutex> lg(mtx_);nullptr == m_pInstance)
{
m_pInstance = make_shared<Singleton>();
}
return m_pInstance.get();
}
};
4.通用的单例模式模板类
依靠C++11的可变模板参数的新特性,我们可以实现一个通用的单例模式的模板类:
/*
懒汉式(延迟加载)
多个线程同时调用getInstance函数时需要等待,因此相对于饿汉式,懒汉式效率不高。如果多个线程频繁调用getInstance函数时,最好使用饿汉式。
*/
template<class T>
class Singleton
{
private:
//构造函数设计成私有的,不能单独用来创建对象。
Singleton() = default;
~Singleton() = default;
//单例模式不能复制,也不能赋值。
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;
public:
//"..."表示可变模板参数,参看C++11新特性。
template<class... Args>
static std::shared_ptr<T> getInstance(Args&&... args)
{
if (std::lock_guard<std::mutex> locker(mutex_);nullptr == instance)
{
instance = std::make_shared<T>(std::forward<Args>(args)...);
}
return instance;
}
private:
std::mutex mutex_;
static std::shared_ptr<T> instance;
};
template<typename T> std::shared_ptr<T> Singleton<T>::instance = nullptr;
以上代码在VS2017下编译通过。