Singleton mode of ordinary in C++ 2B literature and art

  • 2020-04-01 21:37:07
  • OfStack

I. ordinary Singleton


#include<iostream>
using namespace std;
class Singleton
{
    public:
        static Singleton* getInstance();
    private:
        static Singleton* instance;
        Singleton() 
        {
            cout<<"constructorn";
            // do something 
        };
        ~Singleton()
        {
            cout<<"destructorn";
            //do something
        }
};
Singleton* Singleton::instance = NULL;
Singleton* Singleton::getInstance()
{
    if(instance == NULL)
        instance = new Singleton();
    return instance;
}
int main()
{
    cout<<"begin mainn";
    Singleton* instance = Singleton::getInstance();
    cout<<"end mainn";
}

However, this constructor will not be called automatically, requiring the user of this class to manually delete instance. This is not good


This is lazy and requires synchronization in multi-threaded situations. You can also write it as hungry Chinese, but in c++ it's not so good to write it as hungry Chinese. If you have multiple singletons and they refer to each other, then hungry Chinese might have problems. Because in C++, the initialization order of the static members of these singleton classes is uncertain.


2. 2B's Singleton


#include<iostream>
using namespace std;
class Singleton
{
    public:
        static Singleton* getInstance();
    private:
        static Singleton* instance;
        Singleton() 
        {
            cout<<"constructorn";
            // do something 
        };
        ~Singleton()
        {
            cout<<"destructorn";
            //do something
        }
        class Garbo
        {
            public:
                ~Garbo()
                {
                    cout<<"Garbo destructorn";
                    if(Singleton::instance != NULL)
                        delete Singleton::instance;
                }
        };
        static Garbo garbo;
};
Singleton* Singleton::instance = NULL;
Singleton::Garbo Singleton::garbo;
Singleton* Singleton::getInstance()
{
    if(instance == NULL)
        instance = new Singleton();
    return instance;
}
int main()
{
    cout<<"begin mainn";
    Singleton* instance = Singleton::getInstance();
    cout<<"end mainn";
}

I used an inner class, Garbo. Since garbo is automatically released after main ends, garbo calls destructor for instance.

Third, literary Singleton


#include<iostream>
using namespace std;
class Singleton
{
    public:
        static Singleton* getInstance();
    private:
        static Singleton instance;
        Singleton() 
        {
            cout<<"constructorn";
            // do something 
        };
        ~Singleton()
        {
            cout<<"destructorn";
            //do something
        }
};
Singleton Singleton::instance;
Singleton* Singleton::getInstance()
{
    return &instance;
}
int main()
{
    cout<<"begin mainn";
    Singleton* instance = Singleton::getInstance();
    cout<<"end mainn";
}

Instance is constructed before the main starts, and is automatically released when the main ends.

But in that case, it's a hunky singleton. If a large number of resources need to be claimed in the constructor, these resources are always present throughout the run phase. And whenever these resources are needed and when they are not.

4. Improved literary Singleton


#include<iostream>
using namespace std;
class Singleton
{
    public:
        static Singleton* getInstance();
    private:
        Singleton() 
        {
            cout<<"constructorn";
            // do something 
        };
        ~Singleton()
        {
            cout<<"destructorn";
            //do something
        }
};
Singleton* Singleton::getInstance()
{
    static Singleton instance;
    return &instance;
}
int main()
{
    cout<<"begin mainn";
    Singleton* instance = Singleton::getInstance();
    cout<<"end mainn";
}

This way, you can construct a singleton as needed, which is lazy.


Related articles: