前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【C++11】 改进我们的设计模式---单例

【C++11】 改进我们的设计模式---单例

作者头像
CPP开发前沿
发布2021-11-16 14:27:11
5900
发布2021-11-16 14:27:11
举报
文章被收录于专栏:CPP开发前沿

单例模式可以保证一个类只有一个实例,通过全局访问点来对类进行操作,在实际的编码中,如果想要开发一个泛型的单例模式,这个单例又能够创建所有的类型对象,就不可避免的遇到构造函数形参类型或者个数不同,导致单例中需要实现很多构造函数的问题,这些工作大部分都是重复的,给编码带来很多重复的工作量。

C++11提供的新特性就可以帮助我们解决这些问题,尤其是实现一个通用的泛型单实例类就可以使用C++11中的可变参数模版消除这种重复,同时又可以使用完美转发避免不必要的内存复制,从而提升程序的性能也增加了代码的灵活性。下面就可以通过两段代码之间的对比来展示C++11新特性的便利和灵活之处。

1 C++11前实现一个泛型单例

一般情况下,构造函数形参不超过6个,如果要实现一个通用单实例模板类可以按照下面进行编写。代码如下:

代码语言:javascript
复制
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新特性的泛型单例

代码语言:javascript
复制
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的说明可以参考下面的文章:

C++中 =defaule 和 =delete 使用

在本文张,上面的代码可以修改为:

代码语言:javascript
复制
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;
};
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-10-24,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 CPP开发前沿 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档