zoukankan      html  css  js  c++  java
  • 单例模式

    ---恢复内容开始---

      单例模式实现方式:将构造函数、拷贝构造函数、赋值构造函数声明为私有的。然后因为不能够创建对象,所以我们必须提供一个接口用于创建一个对象。必须将其声明为static静态成员函数,是指属于类而不属于对象,即整个类只有一份。静态成员函数只能访问静态数据成员,所以数据成员也要声明为静态的。

      

     1 #include<iostream>
     2 using namespace std;
     3 class Singleton
     4 {
     5 public:
     6     static Singleton* Getinstance()
     7     {
     8         //只能构造一个
     9         if (p == NULL)
    10             p = new Singleton();//成员函数可以调用私有成员函数
    11         return p;
    12     }
    13     ~Singleton() { cout << "~Singleton" << endl; }//并未调用对象析构函数
    14 private:
    15     Singleton() { cout << "Singleton" << endl; };
    16     Singleton(const Singleton& other) {};
    17     Singleton& operator=(const Singleton& other) {};
    18     static Singleton* p;
    19 };
    20 Singleton* Singleton::p = NULL;
    21 int main()
    22 {
    23     Singleton* s1 = Singleton::Getinstance();//没有对象,只能通过类来调用静态方法
    24     Singleton* s2 = Singleton::Getinstance();
    25     return 0;
    26 }

      上述单例模式的实现存在两个问题,一是它并未调用析构函数,存在内存泄漏;而是它并不是线程安全的。首先解决内存泄漏问题。引入auto_ptr智能指针即可解决。

     1 #include<iostream>
     2 #include<memory>
     3 using namespace std;
     4 class Singleton
     5 {
     6 public:
     7     static Singleton* Getinstance()
     8     {
     9         //p.get()返回原生指针。
    10         if (!p.get())
    11             p = auto_ptr<Singleton>(new Singleton());//new Singleton,所有权转移
    12         return p.get();
    13     }
    14     ~Singleton() { cout << "~Singleton" << endl; }//并未调用析构函数
    15 private:
    16     Singleton() { cout << "Singleton" << endl; };
    17     Singleton(const Singleton& other) {};
    18     Singleton& operator=(const Singleton& other) {};
    19     //static Singleton* p;
    20     //将裸指针用智能指针来管理
    21     static auto_ptr<Singleton> p;//析构函数会被调用
    22 };
    23 auto_ptr<Singleton> Singleton::p;//对象结束,静态对象也会被销毁。从而调用析构函数。
    24 int main()
    25 {
    26     Singleton* s1 = Singleton::Getinstance();
    27     Singleton* s2 = Singleton::Getinstance();
    28     return 0;
    29 }

      

      也可以用以下的方法解决这个问题:

     1 #include<iostream>
     2  #include<memory>
     3  using namespace std;
     4  class Singleton
     5  {
     6  public:
     7      static Singleton&  Getinstance()
     8      {
     9            static  Singleton instance;//局部静态对象是在运行期初始化。下一次再进入还是先前的对象。
    10            return instance;//返回了引用
    11     }
    12      ~Singleton() { cout << "~Singleton" << endl; }//会调用析构函数
    13  private:
    14      Singleton() { pthread_mutex_init(&mutex) };
    15      Singleton(const Singleton& other) {};
    16      Singleton& operator=(const Singleton& other) {};
    17  };
    18  int main()
    19  {
    20      Singleton&  s1 = Singleton::Getinstance();
    21     Singleton&  s2 = Singleton::Getinstance();
    22      return 0;
    23  }

      第二个问题,要解决线程安全问题,可以引入互斥量。在创建单例对象的时候进行加锁。

     1  #include<iostream>
     2  #include<memory>
     3  #include<pthread.h>
     4  using namespace std;
     5  class Singleton
     6  {
     7  public:
     8      static Singleton* Getinstance()
     9      {
    10         pthread_mutex_lock(&mutex);
    11          if (!p.get())
    12              p =auto_ptr<Singleton>(new Singleton());
    13         pthread_mutex_unlock(&mutex);
    14          return p.get();
    15     }
    16      ~Singleton() { cout << "~Singleton" << endl; }//并未调用析构函数
    17  private:
    18      Singleton() { pthread_mutex_init(&mutex) };
    19      Singleton(const Singleton& other) {};
    20      Singleton& operator=(const Singleton& other) {};
    21      static auto_ptr<Singleton> p;
    22      static pthread_mutex_t mutex;
    23  };
    24  auto_ptr<Singleton> Singleton::p;
    25  pthread_mutex_t Singleton::mutex;
    26  int main()
    27  {
    28      Singleton* s1 = Singleton::Getinstance();
    29     Singleton* s2 = Singleton::Getinstance();
    30      return 0;
    31  }

    ---恢复内容结束---

  • 相关阅读:
    操作符重载
    虚继承
    虚函数(2)
    基类与子类的成员函数的关系
    虚函数
    虚函数的简单应用
    齐国的粮食战
    纯虚函数
    类的继承(2)
    输出自定义日期格式
  • 原文地址:https://www.cnblogs.com/wsw-seu/p/7678247.html
Copyright © 2011-2022 走看看