单例模式可以保证一个类只有一个实例,通过全局访问点来对类进行操作,在实际的编码中,如果想要开发一个泛型的单例模式,这个单例又能够创建所有的类型对象,就不可避免的遇到构造函数形参类型或者个数不同,导致单例中需要实现很多构造函数的问题,这些工作大部分都是重复的,给编码带来很多重复的工作量。
C++11提供的新特性就可以帮助我们解决这些问题,尤其是实现一个通用的泛型单实例类就可以使用C++11中的可变参数模版消除这种重复,同时又可以使用完美转发避免不必要的内存复制,从而提升程序的性能也增加了代码的灵活性。下面就可以通过两段代码之间的对比来展示C++11新特性的便利和灵活之处。
1 C++11前实现一个泛型单例
一般情况下,构造函数形参不超过6个,如果要实现一个通用单实例模板类可以按照下面进行编写。代码如下:
template <class T>
class SingleClass{
public:
//实现0个参数的构造函数
static T* instance(){
if(nullptr == m_pInstance){
m_pInstance = new T();
}
return m_pInstance;
}
//实现1个参数的构造函数
template <typename T0>
static T* instance(T0 arg1){
if(nullptr == m_pInstance){
m_pInstance = new T(arg1);
}
return m_pInstance;
}
//中间具备2,3,4,5个参数的函数不依次实现,这里实现0,1,6个参数
//实现1个参数的构造函数
template <typename T0,typename T1,typename T2,typename T3,typename T4,typename T5>
static T* instance(T0 arg0,T1 arg1,T2 arg2,T3 arg3,T4 arg4,T5 arg5){
if(nullptr == m_pInstance){
m_pInstance = new T(arg0,arg1,arg2,arg3,arg4,arg5);
}
return m_pInstance;
}
//获取单例
static T* GetInstance(){
if(nullptr == m_pInstance) throw std::logic_error("指针没有初始化,需要先使用构造函数进行初始化");
return m_pInstance;
}
//释放单例
static void DestoryInstance(){
if(m_pInstance){
delete m_pInstance;
m_pInstance = nullptr;
}
}
private:
SingleClass(){};
virtual ~SingleClass(){};
SingleClass(const SingleClass &){};
SingleClass &operator = (const SingleClass&){};
static T *m_pInstance;
};
上面代码在实现0-6个形参的构造函数中,为了实现通用(但是也仅仅支持0-6个形参),存在着很多重复的代码编写。这种工作对于编码人员来说是非常繁琐的且不够灵活,下面的代码用C++11的新的特性进行实现,大家可以做个对比。
2 C++11新特性的泛型单例
template <class T>
class SingleClass{
public:
template <typename ...Args>
static T* instance(Args&&... args){
if(nullptr == m_pInstance){
m_pInstance = new T(std::forward<Args>(args)...);
}
return m_pInstance;
}
//获取单例
static T* GetInstance(){
if(nullptr == m_pInstance) throw std::logic_error("指针没有初始化,需要先使用构造函数进行初始化");
return m_pInstance;
}
//释放单例
static void DestoryInstance(){
if(m_pInstance){
delete m_pInstance;
m_pInstance = nullptr;
}
}
private:
SingleClass(){};
virtual ~SingleClass(){};
SingleClass(const SingleClass &){};
SingleClass &operator = (const SingleClass&){};
static T *m_pInstance;
};
如上代码所示,代码中使用了C++11的新特性有三处,分别是:
新特性的使用,没有了重复模板的定义,且再也没有形参个数0-6的限制,可以实现任意参数的模板;完美转发可以将参数的原始定义转发到构造函数中,右值引用也可以减少内存复制,提升代码性能。
当然,在上面的单例构建中,还可以仅需进行优化,不知道大家有没有注意到在private定义的部分,单实例类的默认构造函数,析构函数,拷贝构造函数,拷贝赋值函数通过定义成private的方式,禁止编译器提供这几种函数,除了写在private还可以通过=delete的方式禁止编译器默认生成,=delete的说明可以参考下面的文章:
在本文张,上面的代码可以修改为:
template <class T>
class SingleClass{
public:
SingleClass() =delete;
virtual ~SingleClass() =delete;
SingleClass &operator = (const SingleClass&) =delete;
SingleClass(const SingleClass &) =delete;
template <typename ...Args>
static T* instance(Args&&... args){
if(nullptr == m_pInstance){
m_pInstance = new T(std::forward<Args>(args)...);
}
return m_pInstance;
}
//获取单例
static T* GetInstance(){
if(nullptr == m_pInstance) throw std::logic_error("指针没有初始化,需要先使用构造函数进行初始化");
return m_pInstance;
}
//释放单例
static void DestoryInstance(){
if(m_pInstance){
delete m_pInstance;
m_pInstance = nullptr;
}
}
private:
static T *m_pInstance;
};